Skip to content
doze
0.2

These are the docs for doze 0.2.

What changed in each release →

AWS

Run local AWS (S3, SQS, SNS, DynamoDB, Lambda and more) as one service, with buckets, queues and tables declared in doze.hcl.

On this page

Runs AWS · macOS and Linux · registry page ↗

Run the AWS services your app calls on your machine, with the buckets, queues, topics and tables declared in doze.hcl, behind one endpoint every AWS SDK understands.

One aws block is one process from the doze AWS project, written in Go: S3, SQS, SNS, DynamoDB (with Streams), Lambda, EventBridge, KMS, SSM Parameter Store, Secrets Manager, STS and Step Functions behind one gateway, with a web console at /_console. No Docker, no JVM. It is for building and testing, not a stand-in for AWS in production.

There is no version: the services follow the current AWS APIs.

Larder, the made-up shop in these docs, keeps product images and receipts in S3 and hands pick lists to the warehouse over SQS:

module aws "aws" {
port = 4566
bucket "product-images" {}
bucket "receipts" { versioning = true }
queue "pick-lists" {
dlq = "auto"
max_receives = 5
}
}

Everything inside is created when the service first starts, updated when you change it, and kept on disk across sleeps. dlq = "auto" makes a pick-lists-dlq queue and sends a message there after five failed receives.

app "catalog" {
run = "go run ./services/catalog"
port = 8002
env = {
AWS_ENDPOINT_URL = module.aws.url
IMAGES_BUCKET = "product-images"
}
}

Every current AWS SDK reads AWS_ENDPOINT_URL. Resources are plain names. The SDK still wants credentials and a region; the local services accept any. From a terminal, doze env prints all of it:

Terminal window
eval "$(doze env aws)"
aws s3 ls
aws sqs get-queue-url --queue-name pick-lists

doze env exports AWS_ENDPOINT_URL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION.

With names on, the service is reached at its name: a block called aws in a stack called shop is http://aws.shop.doze (with port declared, that port is added). Every name under it reaches it too, so SDKs that put the service or the bucket in the host work unchanged: sqs.us-east-1.aws.shop.doze, and S3 by virtual host (uploads.s3.us-east-1.aws.shop.doze) without force_path_style. routes = false keeps it on its port only. See Names and addresses.

module aws "aws" {
queue "emails" {
dlq = "auto"
max_receives = 5
}
queue "orders.fifo" { fifo = true }
topic "signups" {
subscribe {
queue = "emails"
raw = true
}
}
}

A subscribe block in a topic delivers each message to a queue (or a Lambda or an HTTP endpoint).

module aws "aws" {
table "sessions" {
key = "session_id:S"
ttl = "expires_at"
}
}

key is "name:type", with a sort key after a space: "pk:S sk:N". Streams are on, so a Lambda can follow a table’s changes.

module aws "aws" {
function "resize" {
code = "./functions/resize"
timeout = 10
}
rule "order-placed" {
pattern = "{\"source\":[\"shop.checkout\"]}"
targets = ["lambda:resize", "queue:emails"]
}
}

code is a folder with a bootstrap executable (the provided.al2 runtime); the function runs as a local process. PutEvents on the default bus delivers to every rule whose pattern matches.

module aws "aws" {
key "app" {}
parameter "/app/feature/banner" { value = "on" }
secret "db-password" { value = "local-only" }
}

/_console on the service’s address has a page per service: browse buckets and objects, peek at and purge queues, scan tables, invoke functions. Its Traffic tab shows every API call your app makes. In the app it is the service’s Console tab.

The AWS console in the doze app, showing Larder’s buckets and queues

Every doze-aws service — S3, SQS, SNS, DynamoDB, Lambda, EventBridge, Step Functions, Kinesis, API Gateway, CloudFormation, IAM, KMS, SSM, Secrets Manager, STS — behind one gateway on one endpoint, as one doze instance. Declare buckets, queues, topics, tables, functions, rules, keys, secrets, parameters and state machines as nested blocks (the same resource graph doze-aws compiles a CloudFormation template down to); doze converges them on boot. A stock SDK or the aws CLI points AWS_ENDPOINT_URL at the one endpoint; the web console at /_console manages everything, with the live Flows graph and a Traffic tail capturing every call. One process, no Docker, no JVM, no LocalStack.

module aws "local" {
port = 4566
bucket "uploads" { versioning = true }
queue "emails" {
dlq = "auto"
max_receives = 5
}
queue "orders" {
fifo = true
content_dedup = true
}
topic "signups" {
subscribe {
queue = "emails"
raw = true
}
}
table "sessions" {
key = "session_id:S"
ttl = "expires_at"
}
function "resize" {
code = "./functions/resize" # dir with a provided.al2 bootstrap
timeout = 10
}
rule "order_placed" {
pattern = "{\"source\":[\"shop.checkout\"]}"
targets = ["lambda:resize", "queue:emails"]
}
key "app_key" {}
secret "db_password" { value = "s3cr3t" }
parameter "/app/feature/banner" { value = "hello" }
state_machine "order_flow" {
definition = <<-ASL
{
"StartAt": "Resize",
"States": {
"Resize": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:000000000000:function:resize",
"Retry": [{"ErrorEquals": ["States.TaskFailed"], "MaxAttempts": 2}],
"Next": "Notify"
},
"Notify": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage",
"Parameters": {"QueueUrl": "http://localhost:4566/000000000000/emails", "MessageBody.$": "$"},
"End": true
}
}
}
ASL
}
}

This engine takes no version =: it tracks current APIs.

This engine has no top-level fields of its own. Every module block also takes doze’s own fields: port, listen, sleep, after, enabled, routes, count and for_each (doze.hcl reference).

bucket "<name>" { … } — One S3 bucket (the label is the bucket name).

Field Type Default Description
versioning bool false Enable object versioning.
object_lock bool false Enable object lock (implies versioning).

queue "<name>" { … } — One SQS queue; dlq = “auto” creates and wires a dead-letter companion.

Field Type Default Description
fifo bool false FIFO queue (name gets .fifo).
dlq string — “auto” or an existing queue name.
max_receives number — Receives before dead-lettering.

topic "<name>" { … } — One SNS topic with subscribe blocks (queue/lambda/http, filter, raw).

No fields: the label is the declaration.

table "<name>" { … } — One DynamoDB table; key uses the “pk:S sk:N” shorthand, plus gsi/lsi blocks.

No fields: the label is the declaration.

function "<name>" { … } — One Lambda function running as a real local process (code = local dir).

No fields: the label is the declaration.

rule "<name>" { … } — One EventBridge rule; targets use “queue:name”/“topic:name”/“lambda:name”.

No fields: the label is the declaration.

key "<name>" { … } — One KMS key with real local crypto.

No fields: the label is the declaration.

secret "<name>" { … } — One Secrets Manager secret (never stomped without force).

No fields: the label is the declaration.

parameter "<name>" { … } — One SSM parameter (the label is the full /path).

No fields: the label is the declaration.

state_machine "<name>" { … } — One Step Functions state machine, run locally against the stack’s functions, queues and topics.

Field Type Default Description
definition string — The States Language document — a heredoc, or file(“./flow.asl.json”). Required.
role string — Role ARN; the API requires one and nothing local evaluates it, so it defaults.
type string STANDARD STANDARD or EXPRESS (Express executions arrive after Standard ones).

The releases of the module that provide this engine. doze picks the newest one that fits your doze and your version =, and pins it in doze.lock; you never write these. Older releases stay available for pinned lockfiles.

Release Engine versions Platforms
0.2.0 3 stable
0.1.1 3
0.1.0 3

Signed data: index.yaml ↗ · meta.yaml ↗