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.

Anatomy

The Driftfile says which source fills which slot on a slice that already exists. The top level carries slice — a reference to that slice — then four resource sections (atomic, backbone, canvas, domains), each optional and independent (a static site needs only slice and canvas; a data pipeline needs only atomic and backbone), and three optional siblings: environments (which slice each environment applies to), hooks (local pre/post-deploy commands), and tests (e2e commands for drift file test).

No section carries a size. How big anything is, and what it costs, belongs to the slice and is chosen in the slice's shape.

slice: my-app             # required: the slice this file is applied to

atomic:                   # optional: the functions to deploy
  egress:  { ... }
  functions:
    - route: ping
      method: get
      handler: GetPing
    - route: report
      method: post
      handler: PostReport

backbone:                 # optional: what to seed, and the secrets to set
  nosql:    [ ... ]        # each entry names the slot it seeds
  sql:      [ ... ]        # schemas and seeds
  blobs:    [ ... ]
  queues:   [ ... ]
  cache:    { ... }
  secrets:  { ... }

canvas:                   # optional: the site(s) to publish
  sites: [ ... ]

domains:                  # optional: custom hostnames to attach
  - host: forms.example.org

environments:             # optional: one slice per environment
  prod: {}
  staging: {}

hooks:                    # optional: local pre/post-deploy commands
  pre_deploy:  [npm run build]
  post_deploy: [./smoke.sh]

tests:                    # optional: e2e commands for `drift file test`
  e2e: [npx playwright test]

Which slice this applies to

The top of the file names its target. It is a reference to a slice drift slice create made, not a name this file mints — applying a file whose slice does not exist is refused, and the refusal names drift slice create.

TypeDefaultMeaning
  • slice
    Type
    string
    Default
    required
    Meaning
    The slice this file is applied to. 1–32 lowercase letters, numbers, or hyphens. With environments, prod applies to this bare name and every other environment to slice-<env>.

Keys that moved to the slice's shape

Seventeen capacity keys are still accepted and are ignored. The value stays where you wrote it, nothing reads it, and drift file lint says so once per key. They are not removed, so an older Driftfile keeps applying unchanged — it just no longer decides these.

KeyNow set in
log_retentionLog retention
backup_retentionBackup retention
atomic.atomic_sizeCode & dependencies
atomic.function_timeoutFunction timeout
atomic.rate_limitRequests per minute
atomic.deploy_historyDeploy history
atomic.functions[].memorythe function's row
backbone.blob_max_sizeBlob object size
backbone.blob_max_countthe bucket list
backbone.queue_max_depthDefault queue depth
backbone.secret_max_sizeSecret size
backbone.locksConcurrent locks
backbone.realtime_connectionsRealtime connections
backbone.nosql[].sizethe collection's row
backbone.sql[].sizethe database's row
backbone.blobs[].sizethe bucket's row
canvas.canvas_sizeSite storage

Keys that were renamed

These moved within the file. Every old spelling still parses and is rewritten for you, so an existing Driftfile keeps working; the notice names the new one once.

Write insteadWhy
  • name
    Write instead
    slice
    Why
    It references a slice rather than naming a project.
  • atomic.functions[].name
    Write instead
    route + method
    Why
    One string became two fields, so neither has to be parsed out of the other.
  • backbone.nosql[].name
    Write instead
    slot
    Why
    The entry references a collection the slice already holds.
  • canvas.sites[].route
    Write instead
    path
    Why
    Consistent with where a site mounts.

Names

One identifier shape covers almost everything you name: the slice, every environment, every function route, collection, bucket, and queue. 1–32 characters, lowercase letters and digits, hyphens allowed in the interior only. No underscores, no uppercase, no leading or trailing hyphen.

# pattern: ^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$
permit-types      # fine
audit-log-2       # fine
Permit_Types      # rejected: uppercase and underscore
-uploads          # rejected: leading hyphen

SQL database names are the one exception: 1–64 characters, and underscores are allowed in the interior. That is why the SQL section states its own rule.

Short forms

Three sections accept sugar for their common case. The CLI expands it before validating.

Written asMeans
canvas: ./sitecanvas: { sites: [./site] }
canvas: [./a, ./b]canvas: { sites: [./a, ./b] }
atomic: [submit, notify]atomic: { functions: [submit, notify] }
environments: [prod, staging]Each environment applies to its own slice, inheriting the base unchanged
queues: [validate]queues: [{ name: validate }]

drift file fmt preserves whichever form you wrote. Tidying a file never restructures it.