Overcast is alpha — behaviour and APIs may change between releases. Pin your version and read the changelog before upgrading.

overcast

Performance and memory

The startup, memory and image-size targets, what each storage backend costs at startup, and where client-side wall time goes when a workflow feels slow.

Overcast targets sub-50 ms startup, under 15 MiB at idle, and low per-request overhead. CI pipelines should not wait for the emulator.

Targets

MetricTarget
Startup time< 50 ms, spawn to ready — see the per-backend table below
Idle memory< 15 MiB
Docker image (slim)< 40 MiB — Go binary only, no web console
Docker image (console)< 100 MiB — includes web management console
Request overhead (emulator-added latency)< 1 ms for simple operations

Every claim here is measured with default settings, including OVERCAST_EKS_MODE=mock. The opt-in EKS live mode (OVERCAST_EKS_MODE=live) launches k3s containers and costs materially more at startup and in memory by design; treat it as a separate operating profile.

Per-backend startup (cold start, empty data dir)

BackendInternal startup_msWall spawn-to-ready
memory1–2 ms~40 ms
hybrid (auto, when persisting)4–5 ms~40 ms
wal (append log, async fsync)5–8 ms~40 ms
persistent (SQLite)2–6 ms~40 ms

The two SQLite-backed backends (hybrid and persistent) defer the modernc/sqlite cold-migrate cost (~200–340 ms) off the critical path: the migration runs in a background goroutine and the first DB-touching request blocks on it. memory and wal use no SQLite and never pay it at all.

Each row was measured with OVERCAST_STATE set explicitly to that backend. The default, auto, costs whichever row it resolves to plus a negligible resolution check — see The auto default. The overcast-slim image and the overcastd binaries have no SQLite, so their durable option is wal — see Builds without SQLite. Where /data lives and how the hybrid backend flushes are what move these numbers on a real machine — see Storage tuning.

Measurement conditions

Measured 2026-04-17 in the dev container (Debian 12, x86_64, Go 1.23, modernc/sqlite pure-Go driver, every service registered, no SDK clients connected) with OVERCAST_STATE=<backend>, OVERCAST_DATA_DIR=<empty tmp>, polling /_overcast/metrics every 5 ms from a sibling Go process. Wall time is os.Process.Start → first HTTP 200 on /_overcast/metrics. Internal startup is startup_duration_ms from that endpoint (package-init startTime → end of router.New()). Numbers are best-of-5 cold runs (fresh tmp dir each iteration); warm-cache runs are 1–2 ms faster across the board and not reported.

Client-perceived latency — where “Overcast feels slow” actually goes

Fast request handling does not guarantee a fast-feeling workflow. When a tool like the CDK drives Overcast, most of the wall-clock time the user experiences is spent in the client. Establish which side owns the time before assuming it is the emulator: every real AWS API call is logged at INFO by default (see OVERCAST_LOG_LEVEL), so docker logs --timestamps shows every request’s duration and, by omission, every gap where the emulator was idle.

Worked example, measured 2026-07-19 (Docker Desktop on Windows 11 / WSL2, hybrid backend; a CDK v2 bootstrap-and-deploy of four application stacks that took ~45 s wall-clock while every Overcast response completed in <200 ms):

SegmentWall timeOwnerNotes
CDK CLI (Node.js) startup~5 sclientbefore the first request reaches Overcast
Toolkit stack check/deploy~5.4 sclientdominated by CDK poll intervals; responses <200 ms
cdk synth~8.4 sclientzero requests hit the emulator during this gap
4 × app stack deploy~21 sclient~5.1 s per stack = one SDK waiter minDelay; see below
Emulator processing (total)<2 sOvercastsum of all request durations across the entire window

The SDK-waiter tax. Stack provisioning is asynchronous: CreateStack / ExecuteChangeSet return *_IN_PROGRESS and a goroutine provisions the resources, typically in milliseconds (probe: a 3-resource stack reached CREATE_COMPLETE 184 ms after CreateStack, measured by polling DescribeStacks every 100 ms with curl). But the AWS SDK waiter checks immediately, sees IN_PROGRESS because provisioning started microseconds earlier, then sleeps its 5 s minDelay before looking again. Every fast stack therefore costs one full waiter cycle regardless of emulator speed. Overcast shortens that window with a bounded synchronous wait (OVERCAST_CFN_SYNC_WAIT_MS, default 1000 ms) so the waiter’s first check on a fast stack already sees the terminal status — see CloudFormation.

What the emulator cannot fix: CDK CLI startup, cdk synth, and any other client-side work show up as request-log silence. Report those upstream or restructure the workflow (for example cdk deploy --concurrency); no Overcast change will touch them.