Skip to content

Recipes — Workflows

How to drive doze day to day: getting connection strings into your code, running tests and dev servers, operating the stack, and CI.

Ensures the daemon is up, runs your command, and propagates its exit code. Instances boot on first connect and reap after — so run guarantees the backends are awake before your command touches them.

Terminal window
doze run -- npm test
doze run -- go test ./...
doze run -- python manage.py runserver

run injects nothing into the environment. Your command connects using the connection strings you already configured (see below).

doze doesn’t export env vars for you. There are three honest ways to get a connection string into your app:

1. Stable URLs from explicit ports (the simple default). Every instance listens on the explicit port you declared, so its URL is deterministic. Put it straight in your app config or .env:

.env
DATABASE_URL=postgresql://app:app@127.0.0.1:5432/app
REDIS_URL=redis://127.0.0.1:6379
AWS_ENDPOINT_URL_S3=http://127.0.0.1:9000

Connecting cold-boots the instance, so psql postgresql://app:app@127.0.0.1:5432/app just works whether or not it was already awake.

2. Declare the app as a process block (zero-config injection for your apps). When doze supervises your app, it injects each dependency’s connection string (its env_var → URL) into the process environment automatically:

process "api" {
command = "go run ./cmd/api"
depends_on = { postgres.app = "healthy", valkey.cache = "healthy" }
}
Terminal window
doze up # boots app + cache, then runs api with DATABASE_URL/REDIS_URL set
doze logs api -f # follow it

3. Read the manifest (for tooling). The daemon writes .doze/endpoints.yaml with every instance’s address and connection string — machine-readable, for scripts that would rather parse than hardcode.

Wrap your suite so the backends are up, then connect via the stable URL:

Terminal window
doze run -- pytest
doze run -- go test ./...

Want a clean slate between runs? doze reset wipes an instance’s data and re-converges its declared structure (roles, databases, schemas) on the next connect — your schema back, no rows:

Terminal window
doze reset app # wipe app's data
doze run -- pytest # fresh schema, re-provisioned on first connect

For parallel suites that need isolation, give each worker its own database within one instance (e.g. a test_${worker} database your test harness creates and drops), rather than a separate engine per worker.

Terminal window
doze up # converge structure + boot every enabled service, then detach
doze up api worker # just these (and their deps)
doze down # sleep everything and stop the daemon
doze wake app # boot one service now (and its deps)
doze wake # warm every enabled service
doze sleep app # reap one service (and its dependents); daemon keeps running
doze sleep # reap all awake services
doze sync # reconcile declared structure (create/update/prune)
doze sync --dry-run # preview the changes; boots nothing
Terminal window
doze status # grouped table: state, endpoint, conns, MEM, CPU, deps
doze status --graph # the dependency tree
doze ls # alias for status
doze dash # interactive TUI: select a row, then b boot / d reap / R restart / f follow
doze logs # aggregate logs of every running service
doze logs app -f # follow one service's logs
doze doctor # diagnose config, platform, toolchains, daemon state
doze binaries available [engine] # versions from the mirror (installed/pinned marked)
doze binaries list # resolved/cached toolchains per instance

doze status works even when the daemon is stopped (it shows declared, on-disk state). A backend that failed to boot shows state error with the reason; piped output is plain (no color), so it’s safe in scripts.

Simplest — wrap the test command so the backends are up:

Terminal window
doze run -- go test ./...

Or bring the stack up once and reuse it across steps (connections boot what they touch):

Terminal window
doze up # converge + boot, then detach
./run-migrations && ./integration-tests
doze down # sleep everything and stop the daemon

Tips for CI:

  • Commit doze.lock so the binaries are byte-identical to local.
  • Use DOZE_<ENGINE>_BINDIR to point at preinstalled binaries and skip downloads.
  • idle_timeout can be short; the daemon reaps idle backends between steps.