Recipes — Full stacks
Putting it together: realistic, polyglot environments declared in one place and wired into apps with zero hardcoded ports.
A typical web app: Postgres + cache + object storage + queue
Section titled “A typical web app: Postgres + cache + object storage + queue”defaults { idle_timeout = "10m" }
postgres "app" { version = 16 owner = "app" role "app" { password = "app" } grant { role = "app" database = "app" privileges = ["ALL"] } extensions = ["uuid-ossp", "pg_trgm"]}
valkey "cache" { version = 9 maxmemory = "256mb"}
s3 "uploads" { bucket "user-uploads" {} bucket "exports" {}}
sqs "jobs" { queue "email" {} queue "export" {}}doze run -- ./bin/server # gets DATABASE_URL, REDIS_URL, # AWS_ENDPOINT_URL_S3, AWS_ENDPOINT_URL_SQS, AWS_* credsdoze run -- ./bin/worker # same env; processes the queuesEvent-driven services: SNS fanout into SQS
Section titled “Event-driven services: SNS fanout into SQS”sqs "bus" { queue "email-svc" {} queue "audit-svc" {}}
sns "events" { sqs = "bus" topic "user-events" {} subscribe "user-events" { protocol = "sqs" endpoint = "email-svc" raw = true filter = { type = ["signup", "password_reset"] } } subscribe "user-events" { protocol = "sqs" endpoint = "audit-svc" # gets everything (no filter) raw = true }}Publishing to user-events fans out to both queues, with email-svc receiving
only the filtered subset.
Mongo-style service
Section titled “Mongo-style service”ferret "docs" { version = "2.7" port = 27017}doze run -- ./svc injects MONGODB_URI; doze runs the private Postgres + Mongo
gateway for you — one self-contained engine, nothing to wire up.
The kitchen sink (everything at once)
Section titled “The kitchen sink (everything at once)”Split across *.doze.hcl for readability — see config layout.
defaults { idle_timeout = "10m" }postgres "app" { version = 16 role "app" { password = "app" }}valkey "cache" { version = 9 }kvrocks "kv" { version = 2 }ferret "mongo" { version = "2.7" port = 27017}s3 "blob" { bucket "data" {}}sqs "queue" { queue "tasks" {}}sns "topic" { sqs = "queue" topic "events" {} subscribe "events" { protocol = "sqs" endpoint = "tasks" raw = true }}doze status # one view of the whole environmentdoze dash # live, interactivedoze run -- make integration-testFramework wiring
Section titled “Framework wiring”doze injects the standard env vars apps already read — usually no code changes.
Rails — reads DATABASE_URL and REDIS_URL:
doze run -- bin/rails serverdoze run -- bin/rails testDjango (with dj-database-url) — reads DATABASE_URL:
doze run -- python manage.py migratedoze run -- python manage.py runserverNode / Prisma — DATABASE_URL; AWS SDK reads AWS_ENDPOINT_URL_S3 + creds:
doze run -- npx prisma migrate devdoze run -- npm run devGo — read the env directly:
db, _ := sql.Open("pgx", os.Getenv("DATABASE_URL"))rdb := redis.NewClient(opt(os.Getenv("REDIS_URL")))s3c := s3.NewFromConfig(cfg, func(o *s3.Options){ o.BaseEndpoint = aws.String(os.Getenv("AWS_ENDPOINT_URL_S3")) o.UsePathStyle = true})doze run -- go run ./cmd/apiWith multiple instances of the same engine, use the per-instance
DOZE_<NAME>_URL (the conventional DATABASE_URL/REDIS_URL is only set when a
single instance claims it).