Deploy & hosting
putnami deploy ships a project to Putnami Cloud and runs it. The verb activates
on a project's infra/runtime.json; that file declares how the service is hosted
— ingress, scaling, resources.
A deploy is a pure function of versioned state: it publishes the project's artifacts, then releases a new revision that is attributable to a specific commit. Zero-downtime cutover is the default, and the previous revision stays available to roll back to.
Deploy
putnami deploy| Want to… | Do this |
|---|---|
| Deploy a specific environment | putnami deploy --env <env> |
Block until serving traffic converges, or a terminal Partial/Failed outcome |
putnami deploy --wait |
| Preview the plan without provisioning | putnami deploy --preview |
| Re-roll even when content is unchanged | putnami deploy --force |
Start with the walkthrough: Your first deploy.
Where your image goes
A deploy publishes your container image to the platform OCI registry, then asks the control plane to run that exact digest. You declare one coordinate:
{
"options": {
"publish": { "dockerRegistry": "oci.putnami.dev/<namespace>" }
}
}Declare the bare host or a namespace under it; both work. With nothing declared,
the deploy uses oci.putnami.dev.
The control plane copies the published digest into the registry your runtime
pulls from and pins the new revision to the copy. You do not name that registry,
grant it access, or know which cloud it belongs to — the request carries only the
registry you published to and the digest you published. That is the same request
whether you run putnami deploy on your laptop or a CI pipeline deploys for you,
so both paths roll the identical image.
Declaring a cloud provider registry path instead (for example
<region>-docker.pkg.dev/<project>/<repo>) skips the copy: the revision pulls
straight from where you published. Use it only when you own that registry.
Hosting: infra/runtime.json
A deployable project declares its runtime in infra/runtime.json. The fields
below are verified against services running in production today; the
managed runtime page covers scaling, config, and
bindings in depth.
{
"ingress": { "domains": ["service.example.com"] },
"scaling": { "max": 2, "concurrency": 500 },
"resources": { "cpu": "1000m", "memory": "512Mi" }
}| Field | Meaning |
|---|---|
ingress.domains |
custom hostnames the service answers on |
ingress.public |
set false for an internal-only service (no public URL) |
scaling.max |
maximum active instances; the CPA always owns a zero floor |
scaling.concurrency |
requests per instance before scaling out |
resources.cpu / memory |
per-instance resources |
security.platformAuth |
"disabled" when the service handles its own authentication |
Infra protocol v2 does not expose scaling.min. All managed services scale to
zero and use request-based CPU; those settings are CPA-owned platform invariants
rather than manifest options. A workload that must continue after an HTTP
response must use a job or worker execution contract instead of changing the
service billing posture.
Public vs authenticated
Ingress controls reachability. Set ingress.public: false for a service with no
public URL. A public service that owns its own authentication declares
security.platformAuth: "disabled"; use the current runtime schema when the
platform, rather than the service, is to enforce authentication.
Generated HTTP route intent
Frameworks may emit a canonical route inventory at
.gen/schema/http-routes.json. Deploy carries that artifact byte-for-byte,
validates the putnami.http-routes.v1 protocol and digest before provisioning,
and records the exact inventory on the deployment. A route-only change or
removal is release content, so it prevents an otherwise-unchanged deploy from
being skipped.
Path enforcement is default-off. A project opts its release into the generated
route policy through putnami.json:
{
"options": {
"@putnami/cloud": {
"deploy": { "enforceHttpRoutes": true }
}
}
}The managed Putnami gateway currently suspends this opt-in at the operator
master switch (#2744): generated artifacts are still carried and validated,
but the effective gateway policy remains host-to-service routing without a
path/method allowlist. Do not rely on enforceHttpRoutes for 404 filtering
until a scalable replacement is announced.
An opted-in deploy fails before provisioning when the generated artifact is
missing, malformed, noncanonical, or uses an unsupported protocol version.
Without the setting, a project that emits no artifact keeps the existing
hostname-level routing behavior. When the managed gateway, its shared reject
backend, and the operator master switch are configured, enforcement projects
only publicEdge: true exact,
slash-terminated prefix, and supported segment-template paths to the workload;
all unmatched paths go to the reject backend without invoking the workload's
Cloud Run service. Removing a declared path removes its gateway rule. Disable
the setting and redeploy to roll the host matcher back to legacy host-default
routing. Each public route method is enforced with an exact gateway :method
match; undeclared methods and private methods on the same path go to the reject
backend without reaching the workload.
Pages
| Page | Status |
|---|---|
| Your first deploy | Ready |
| Environments follow channels | Ready |
| Environments (prod, preview, per-env config) | Planned |
| Preview environments (per-branch URLs) | Planned |
| Rollback | Planned |
| Ingress & custom domains | Planned |
| Public vs authenticated services | Planned |