The Local Development page covers the AWS-bound loop (ds run backend + ds run ui against your personal SST stage). This page covers the fully-local, no-AWS alternative: a docker-compose stack that runs many independent DevStride instances at once — one per git worktree — on a single machine.
Each instance has its own branch, its own ports, and its own isolated dataset. They all share one set of heavy infra containers, so ~10 instances stay cheap.
.env stage binding, and no sso login required for this flow.docker/ scripts and the ds worktree CLI). master and develop both have it. New worktrees inherit these files from their base branch. ┌─────────────────────────────────────────────┐
shared core │ postgres dynamodb minio cognito-local │ (started once)
(devstride-core)└─────────────────────────────────────────────┘
▲ ▲ ▲
┌────────────────┼────────────┼──────────────┼────────────────┐
│ instance "main"│ │ instance "featx" │ ...
│ backend :4000 │ │ backend :4001 │
│ frontend :8080 │ │ frontend :8081 │
│ soketi :6001 │ │ soketi :6002 │
│ db devstride_main │ db devstride_featx │
│ tables main-devstride-* │ tables featx-devstride-* │
│ buckets main-devstride-* │ buckets featx-devstride-* │
└────────────────────────────┴───────────────────────────────┘
postgres, dynamodb, minio, cognito-local. Heavy and stateful, started once, reused by every instance.backend + frontend + tiny soketi, bind-mounting that worktree's source. Isolation inside the shared infra is logical: each instance gets its own Postgres database, its own DynamoDB tables, its own MinIO buckets, its own Cognito user pool, and its own soketi app.main (index 0, ports 4000/8080), brought up by ds run local. Extra worktrees are indexes 1, 2, 3…IS_LOCAL + DEVSTRIDE_LOCAL_STACK so production, sst dev, and tests are completely untouched. You don't need to know the internals to use the stack, but it's why this flow needs no AWS credentials.If you only want the main checkout running locally:
ds run local # shared core + the "main" instance (first run: a few minutes)
ds worktree cli main migrations run # apply schema (first time / after new migrations)
ds worktree cli main golden build # seed the Acme golden dataset + Cognito + aggregation recalc
Open http://localhost:8080.
# 1) Create a new instance on its own new branch + worktree, and start it.
ds worktree create featx
# → git worktree add, allocate ports, ensure the core is up, provision this
# instance's data, start it detached, and print its URLs.
# 2) Apply schema + seed data (each instance starts with an EMPTY database).
ds worktree cli featx migrations run
ds worktree cli featx golden build # optional: seed golden Acme
# 3) Open it — frontend on http://localhost:8081 (backend :4001).
# 4) See everything running.
ds worktree ls
# 5) Tear it down (stops it, drops its data + worktree; KEEPS the branch).
ds worktree rm featx
That's the whole loop.
| Command | What it does |
|---|---|
ds run local | Bring up the shared core + the primary main instance in the foreground. |
ds worktree create <name> | git worktree add a new branch, allocate ports, ensure the shared core is up, provision this instance's data, start it detached, print URLs. |
ds worktree ls | List instances: name, slug, index, status, frontend/backend URLs, branch. |
ds worktree cli <name> <cmd...> | Run any cli/commands/<cmd> inside that instance's backend (e.g. migrations run, golden build, data copy). |
ds worktree logs <name> [service] | Follow logs (service ∈ backend, frontend, soketi, bootstrap). |
ds worktree up <name> | Start a previously-created instance (after down). |
ds worktree down <name> | Stop an instance, keeping its data. |
ds worktree rm <name> | Stop + drop all of this instance's data (db, tables, buckets, cognito pool) + remove the worktree. Keeps the git branch; prompts if the worktree has uncommitted changes. |
ds worktree core up | Start just the shared core. |
ds worktree core down [--wipe] | Stop the shared core (--wipe also deletes all shared data volumes). |
create flags-b, --branch <branch> — branch to create/check out (default: the slug).--from <ref> — base ref for the new branch (default: current HEAD).--rebuild — rebuild the shared devstride-local image first (after dependency changes).--attach — run in the foreground instead of detached.rm flags--keep-data — skip dropping the shared-core resources (just stop + remove the worktree).--delete-branch — also delete the git branch (kept by default).-f, --force — skip the confirmation when the worktree has uncommitted changes.Derived from a per-instance index i (index 0 = main):
| Service | Port |
|---|---|
| backend | 4000 + i |
| frontend | 8080 + i |
| soketi | 6001 + i |
Shared core ports are fixed: postgres 5432, dynamodb 8000, minio 9000/9001, cognito-local 9229. ds worktree ls always prints the resolved URLs.
This is the whole point of the setup: every instance owns a completely separate copy of the data, so you can run several branches at once, each backed by a different dataset. The isolation is enforced at the resource level, not by convention:
| Layer | Per-instance resource |
|---|---|
| Postgres | Its own database devstride_<slug> (the CLI patches DB_CONNECTION_STRING inside the instance's DEVSTRIDE_CONFIG secret). |
| DynamoDB | Its own tables <slug>-devstride-{state,timetracking,ai,migrations} inside the shared -sharedDb. |
| MinIO (S3) | Its own buckets <slug>-devstride-* (media bucket is public-read). |
| Cognito | Its own user pool devstride-<slug> in the shared cognito-local. |
| Realtime | Its own soketi container + app, so channels never cross between instances — even two instances holding the same org id. |
Because each instance is a self-contained database, the same data tooling from Local Development works per-instance — you just scope it with ds worktree cli <name>:
ds worktree cli featx migrations run
ds worktree cli featx golden build
golden build seeds the Acme org (ac3e0000-0000-4000-8000-000000000001), creates the Cognito logins in that instance's pool, and runs the final aggregation recalc — all scoped to featx only.
# Copy one org's data from a source database into THIS instance.
# Users land in this instance's cognito pool.
ds worktree cli featx data copy -o <organizationId>
# At a TTY you're prompted to pick a *_CONNECTION_STRING from .env, or pass it:
ds worktree cli featx data copy -o <organizationId> --source GOLDEN_DB_CONNECTION_STRING
The worktree mounts its own ./data directory at /data inside the container, so dumps round-trip through there:
# Import a dump placed under the worktree's ./data.
ds worktree cli featx data import /data/<dump>.json
# Export this instance's database.
ds worktree cli featx data export /data/featx-export
ds worktree cli demo golden build), copy a specific customer org into another (ds worktree cli repro data copy -o <id>), and leave a third empty for a from-scratch flow. They run simultaneously on localhost:8080, :8081, :8082 and never see each other's data.ds worktree cli <name> golden build) — the build ends with an aggregation recalc and is the single source of truth. Never patch rows directly; the next build truncates and regenerates the Acme org, silently discarding manual edits. And prefer golden build (or ds golden import on shared stages) over ds data copy for golden persona orgs — the generic copier is marker-unaware and leaves the golden anchor marker stale.Local auth uses cognito-local, which signs in by username, not email. After a golden build, use username acme.devstride (Admin) or alex.rte (RTE persona), password Demo@123 for all personas. Each instance has its own pool, so the same credentials exist independently on every instance you seed.
ds worktree down <name> — stop an instance but keep its data; bring it back with ds worktree up <name>.ds worktree rm <name> — stop it, drop all its data, and remove the worktree (keeps the branch; prompts on uncommitted changes).ds worktree core down — stop the shared core. This stops the data layer for all instances; add --wipe to also delete the shared data volumes.ds worktree create --rebuild (or ds run local --rebuild).docker/ scripts are bind-mounted from the worktree, so create instances from a branch that contains docker/instance.compose.yml et al. (master, develop, or any branch cut from them).creates are simplest..git/devstride-local/registry.json) and is shared across all worktrees.ds data command surfaceds golden commandsds CLI surfaceLocal Development
The real day-to-day dev loop: running the backend and UI, scaffolding CQRS code, migrations, and managing local data with the ds CLI.
Golden Dataset
The ds golden CLI: a scoped, generator-driven demo/test fixture built around the Acme org — what each subcommand does and where the deep-dive docs live.