Skip to content

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" {}
}
Terminal window
doze run -- ./bin/server # gets DATABASE_URL, REDIS_URL,
# AWS_ENDPOINT_URL_S3, AWS_ENDPOINT_URL_SQS, AWS_* creds
doze run -- ./bin/worker # same env; processes the queues

Event-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.

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.

Split across *.doze.hcl for readability — see config layout.

doze.hcl
defaults { idle_timeout = "10m" }
postgres "app" {
version = 16
role "app" { password = "app" }
}
valkey "cache" { version = 9 }
kvrocks "kv" { version = 2 }
mongo.doze.hcl
ferret "mongo" {
version = "2.7"
port = 27017
}
aws.doze.hcl
s3 "blob" {
bucket "data" {}
}
sqs "queue" {
queue "tasks" {}
}
sns "topic" {
sqs = "queue"
topic "events" {}
subscribe "events" {
protocol = "sqs"
endpoint = "tasks"
raw = true
}
}
Terminal window
doze status # one view of the whole environment
doze dash # live, interactive
doze run -- make integration-test

doze injects the standard env vars apps already read — usually no code changes.

Rails — reads DATABASE_URL and REDIS_URL:

Terminal window
doze run -- bin/rails server
doze run -- bin/rails test

Django (with dj-database-url) — reads DATABASE_URL:

Terminal window
doze run -- python manage.py migrate
doze run -- python manage.py runserver

Node / PrismaDATABASE_URL; AWS SDK reads AWS_ENDPOINT_URL_S3 + creds:

Terminal window
doze run -- npx prisma migrate dev
doze run -- npm run dev

Go — 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
})
Terminal window
doze run -- go run ./cmd/api

With 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).