App Hosting Overview
App Hosting lets you deploy a public OCI container image on a dedicated VM, reachable over HTTPS at https://{name}.foundrydb.com, and optionally wired directly to your managed databases over a private SDN network. Your app and its data run in the same region, on the same private backbone, with no public traffic between them.
What App Hosting provides
| Capability | What it does |
|---|---|
| Dedicated VM per app | Your container gets its own VM, not a shared slice. Resource accounting is honest and the failure domain stays small. |
HTTPS at {name}.foundrydb.com | A platform-issued certificate is provisioned before the container serves its first request. No ingress controller to configure. |
| Private database networking | Attach up to five managed databases. The platform peers the networks, opens the firewall, and injects connection credentials as environment variables. |
| Blue/green deploys | A new image or environment change starts the new container alongside the old one. Traffic only cuts over once the new container is healthy. A failed redeploy leaves the previous container serving. |
| Build from source | Point the app at a git repository with a Dockerfile. The platform clones, builds on the app's own VM, pushes to the private platform registry, and deploys the image by digest. |
| Deploy history and rollback | Every successful deploy is recorded as an immutable revision. Roll back to any revision with a single API call. |
| Custom domains | Bring your own hostnames. Certificates are issued and renewed automatically. |
| App-to-app private networking | Attach one app to another. Traffic stays on the private SDN; the target's host, port, and URL are injected as environment variables. |
How it works
Each app runs as a single OCI container on its own VM, managed by a systemd Quadlet unit under Podman. A Caddy HTTPS ingress terminates TLS and proxies to the container port on the VM loopback. The container port is never exposed publicly.
Internet → Caddy (TLS) → container port (loopback) → your app
↕ private SDN
attached databases / apps
A deploy works like this: the platform starts the new container alongside the old one, probes it on its health check path, and cuts the ingress over only once it returns the required number of consecutive 2xx responses. If the probe never goes green within the timeout, the deploy fails and the old container keeps serving.
Lifecycle, end to end
The diagram below traces an app from the create call through to steady-state serving, then loops back through the blue/green redeploy that every subsequent change runs.
The flow has three stretches:
- Bring-up. The
POSTis accepted and the app sits inPending. Provisioning then sets up the dedicated VM and its disks, installs the agent that executes work on the VM, and configures the Caddy ingress (including issuing the TLS certificate for{name}.foundrydb.com). These steps run on one VM and converge before the container starts. - First run. The agent pulls the container image and starts it under a Podman Quadlet unit. Once the container is up and healthy, the app reaches
Runningand Caddy begins terminating TLS on:443and proxying to the container on the loopback. - Steady state and redeploys. While
Running, Caddy serves traffic. Any later change (new image, env, configuration, or attachment) re-enters the pull-and-start step as a blue/green redeploy: the new container is brought up alongside the current one and only takes over once it is healthy.
Runtime model
- One container per VM. Each app is a single OCI container on its own dedicated VM. There is no shared host, no multi-replica scaling, and no orchestration layer between you and the container.
- Podman Quadlet. The container is declared as a systemd Quadlet unit and run by Podman. systemd owns the container's lifecycle on the VM, so it is started on boot, restarted on exit, and managed like any other unit.
- Caddy ingress. A Caddy process on the VM terminates TLS and reverse-proxies to the container port over the loopback interface. The container port is bound to localhost and is never published on the public interface. Caddy is also where blue/green cutover happens: pointing ingress at the new container is what makes a deploy live.
- Private database and app networking. When you attach a managed database or another app, traffic to it stays on the private SDN. The platform peers the networks, opens the firewall, and injects the connection details (and credentials) into the container as environment variables. No attached traffic crosses the public Internet.
- Stateless by default. An app's durable state lives in its attached databases. The container itself is treated as replaceable: each redeploy starts a fresh container from the image.
When to use App Hosting
App Hosting is a good fit for:
- API servers, background workers, or web apps that read from or write to managed databases
- Apps where you want database credentials, firewall rules, and network peering managed for you
- Services you want to redeploy frequently with zero downtime
- Internal services that need to call each other over a private network
It is not a general-purpose container runtime. Each app is one image on one VM. There is no multi-replica horizontal scaling, no container orchestration, and no persistent volume management (apps are stateless beyond their attached databases).
Minimal example
curl -u "$USER:$PASS" -X POST https://api.foundrydb.com/app-services \
-H "Content-Type: application/json" \
-d '{
"name": "my-api",
"plan_name": "tier-2",
"zone": "se-sto1",
"app_config": {
"image_ref": "docker.io/traefik/whoami:latest",
"container_port": 80
},
"storage_size_gb": 10
}'
Provisioning is asynchronous. Poll GET /app-services/{id} until status is Running. The response then includes the public url.
App lifecycle
An app moves through a small set of statuses. Provisioning and redeploys are asynchronous, so the status is how you track progress: poll GET /app-services/{id} and watch it settle on Running (or Failed).
| Status | Meaning | What is happening |
|---|---|---|
Pending | Accepted, waiting for network and VM provisioning to start. | The create call has been recorded and the app is queued. Nothing is serving yet. |
PendingModification | A redeploy, scale, or attachment change is in progress. | The same state covers both first-time provisioning (VM, agent, ingress, certificate, then image pull and start) and later changes. During a redeploy the current container keeps serving until the new one is healthy. |
Running | Container is serving. | The container is up and healthy, Caddy is terminating TLS on :443, and the public url is live. This is the steady state. |
Stopped | Container is stopped. | The container has been stopped and is not serving. The VM, ingress configuration, and attachments are retained so it can be started again. |
Deleting | Teardown in progress. | The platform is removing the container, ingress, certificates, DNS records, and the VM. |
Failed | Provisioning or redeploy failed. | A bring-up step or a health-gated redeploy did not complete. On a failed redeploy the previously healthy container keeps serving and the app holds the previous revision. |
Next steps
- Deploy an App: full create and update reference
- Attachments: connect your app to databases and other apps
- Deployments: zero-downtime redeploys, rollback, and deploy logs
- Custom Domains: bring your own hostnames