Core concepts
A handful of ideas explain everything else in Apprail: where things live, what a deployment actually does, and what your code can count on when it starts.
The model
- Workspace
- Your team’s account. It holds members, API tokens, alert channels, registry credentials, usage, and limits. A token belongs to exactly one workspace.
- Project
- One application — all the services and data it needs. Addressed by its slug (
shop) or ID. - Environment
- A separate copy of the project:
productionandstagingby default, more if you add them, and apr-<number>environment for each pull-request preview. Each has its own variables, data, hostnames, and private network. - Service
- One long-running program, built from one image. A web service listens on a port and gets a public address; a worker has no port and just keeps running. A service is defined once per project and deployed into each environment separately.
- Release
- An immutable snapshot of what runs: the image pinned to its exact digest plus the service’s settings (port, health path, CPU, memory, instances, scaling, pre-deploy command). Rollback and promotion reuse releases; nothing is rebuilt.
- Deployment
- The act of making a release live in one environment, with a recorded history of every step.
- Data resources
- Postgres databases, Valkey caches, RabbitMQ queues, and S3-compatible buckets. They belong to an environment, and every service in it receives their connection variables.
Services are addressed as PROJECT/SERVICE everywhere — shop/web, shop/worker — and commands act on production unless you pass --env.
What a deployment does
Every deployment — from an image, a Git build, a promotion, a rollback, or a settings change — goes through the same steps, visible in the console and in apprail status:
| State | What happens |
|---|---|
awaiting_approval | Only in a protected environment, until an owner or admin approves it. Nothing changes meanwhile. |
queued | Waiting for a worker to pick it up — usually a moment. |
preparing | The image tag is resolved to its digest (with your registry credential if it is private) and recorded as a release. |
releasing | The pre-deploy command runs once, if the service has one. |
canary | If canary releases are on, one instance of the new release takes a share of public traffic for a set time. With blue/green, a full copy of the release starts beside the live one, takes all public traffic at once, and the previous release stands by. |
deploying, health_checking | New instances start and must pass their health check; old instances keep serving until they do. |
ready | The release is live. The previous release is kept for rollback. |
failed | Something went wrong, with the reason attached. The release that was live keeps serving — a failed deployment never takes an app down. |
superseded, cancelled | A newer deployment of the same service and environment replaced it before it finished, or someone stopped or rejected it. |
What your code can count on
- Listen on
0.0.0.0:$PORT. Web services receivePORTset to the service’s port. Listening onlocalhostonly is the most common reason a first deploy fails its health check. - A health check decides when you’re live. Apprail requests the service’s health path (default
/) on each new instance; any 2xx or 3xx answer counts. An instance that isn’t healthy within five minutes fails the deployment. - Graceful shutdown. Before an instance stops — during a rollout or a scale-down — it stops receiving new requests, waits 5 seconds, then gets
SIGTERMand has the rest of 30 seconds to finish. Open WebSocket connections are closed then; clients should reconnect. - Identifiers. Every instance receives
APPRAIL_SERVICE,APPRAIL_ENVIRONMENT_ID,APPRAIL_RELEASE_ID, andAPPRAIL_DEPLOYMENT_ID. - The filesystem is temporary. Anything written to disk disappears on the next deploy or restart. Keep files in object storage and state in Postgres.
- Size. By default an instance gets 250 millicores (a quarter of a CPU) and 512 MB of memory; one instance per environment. Change both with
apprail services update.
Addresses and networking
Each web service gets a generated HTTPS address per environment on apprail.io, shown by apprail status. Add your own domain with Domains.
Inside an environment, services reach each other privately: every service receives APPRAIL_SERVICE_<NAME>_URL (and _HOST, _PORT) for each sibling web service, such as APPRAIL_SERVICE_API_URL=http://api. That traffic never leaves the environment’s network. Environments are isolated from each other and from other workspaces; data resources have no public address at all.
Where it runs
Apprail’s compute region is Šiauliai, Lithuania (lt-sil-1). Your services, workers, jobs, and data all run there. Cloudflare’s global edge sits in front of every public address, terminating TLS close to your visitors. See Network.
The console, CLI, API, and coding agents are four doors into the same system. Anything you do in one is visible in the others, and every change lands in the workspace’s activity history.