drift Docs
Start
What is Drift?
The tour, if you are new here.
Use cases
Whether Drift does your thing.
Getting started
Nothing to deployed, in one command.
Architecture
How a slice is put together.
What it costs
The free grant, four unit prices, two rules.
Build
Canvas
Static sites, same origin as your API.
Tools
Operate
Auth
Accounts, tokens and scopes.
Security
Boundaries, sandboxing and hardening.
Troubleshooting
Error codes
What went wrong, and what to do about it.
Legal
Acceptable use
What a slice may not be used for.
Data processing
The DPA, and every sub-processor.

Environments: per-environment deploys

Ship the same project to several places (production, a staging copy, a throwaway dev slice). Each environments entry is a partial override that deep-merges onto the base; drift file apply <env> selects one and deploys it into that environment's own slice.

Each environment needs its own slice, and you make them yourself.

The name is derived, not declared: prod and production apply to the bare slice, and every other environment applies to <slice>-<env>. That slice has to already exist — create each one in the slice's shape before deploying to it, because applying against a slice that is not there is refused. An override cannot set slice.

So a project with prod and staging is two slices, links and links-staging, each shaped and priced on its own. They are separate in every sense: their own data, their own URL, their own bill.

Driftfile
slice: links                     # prod → the slice "links"
atomic:
  functions:
    - route: shorten
      method: post
      handler: PostShorten
backbone:
  nosql:
    - slot: links

environments:
  prod: {}                          # inherits the base unchanged
  staging:                          # → the slice "links-staging"
    backbone:
      nosql:                       # re-declaring REPLACES the base list
        - slot: links
          seed: ./backbone/demo.jsonl  # staging gets demo rows
  dev: {}                           # → the slice "links-dev"

An override accepts the same sections as the base (atomic, backbone, canvas, domains), and it may not set slice. The capacity keys it also still accepts are ignored wherever they appear, base or override, so an environment can no longer differ in a limit — that difference lives in the two slices' own shapes.

How the merge works

The overlay is a deep merge of the document, and it has exactly two rules:

  • Maps recurse. Setting atomic.egress leaves the rest of atomic alone.
  • Everything else replaces, lists included. A list in an override is the whole list; there is no element-wise merge.

Presence is the signal, not truthiness, and that is what lets an environment express wildcard: false on a domain and have it stick.

A resource list is shared only while an environment stays silent about it.

The example above gives staging exactly one collection entry, the seeded one: re-declaring backbone.nosql replaced the base list wholesale. Leave a list out to inherit it; write it out and you own all of it. Run drift file explain --env staging to see the result before you deploy.
  • The slice is derived, and has to exist: slice for prod/production, slice-<env> otherwise. Each is separately shaped, separately priced, and made with drift slice create before its first deploy.
  • Config lives here; secrets that differ per environment live in .env.<env>. ${ENV} binds to the selected environment.
  • An environment name takes the same identifier shape as a slice name.

This is not a CI pipeline: there is no “deploy staging, test, promote prod” orchestration in the Driftfile. Drift gives the verb; your CI chains it.