The problem
Parallel agents on one database step on each other: one runs a destructive migration while another’s tests expect the old schema, one flushes Redis in the middle of another’s run. For throwaway work each instance should own its backing services and be free to wreck them.
That is the default. A service without scope is isolated: every instance that lists it gets its own container, on a network private to that instance, under the same hostname.
Config
[services.postgres]
image = "postgres:16" # no scope: one per instance
env = { POSTGRES_PASSWORD = "postgres" }
[services.redis]
image = "redis:7"
command = ["redis-server", "--save", "", "--appendonly", "no"] # in-memory only
[sandbox.api]
folder = "../api" # your repo, next to this config dir
image = "node:22"
services = ["postgres", "redis"]
# Your login and settings, from the host.
mounts = ["source=${localEnv:HOME}/,target=/root/,type=bind"]
[sandbox.api.containerEnv] # same hostnames in every instance, its own containers
DATABASE_URL = "postgres://postgres:postgres@postgres:5432/postgres"
REDIS_URL = "redis://redis:6379"
= "/root/"
[sandbox.api.postCreateCommand] # once, when an instance is created
agent = "npm install -g "[services.postgres]
image = "postgres:16" # no scope: one per instance
env = { POSTGRES_PASSWORD = "postgres" }
[services.redis]
image = "redis:7"
command = ["redis-server", "--save", "", "--appendonly", "no"] # in-memory only
[sandbox.api]
folder = "../api" # your repo, next to this config dir
image = "node:22"
services = ["postgres", "redis"]
# Your login and settings, from the host.
mounts = ["source=${localEnv:HOME}/,target=/root/,type=bind"]
[sandbox.api.containerEnv] # same hostnames in every instance, its own containers
DATABASE_URL = "postgres://postgres:postgres@postgres:5432/postgres"
REDIS_URL = "redis://redis:6379"
[sandbox.api.postCreateCommand] # once, when an instance is created
agent = "npm install -g "On macOS keeps its login in the Keychain: run /login once in any instance.
Try it
One instance per task, each with its own postgres and redis:
devsandbox run api --name fix-login
devsandbox run api --name add-search
devsandbox stats # both instances and all four service containers--name: the instance name.
Start in each:
devsandbox exec -it fix-login
devsandbox exec -it add-search devsandbox exec -it fix-login
devsandbox exec -it add-search devsandbox rm add-search removes the instance with its services and network.
How it works
- Services follow their instance through
stop,startandrm. devsandbox service rebuild redisrecreates every running instance’s redis in place (services reference).- No host
portson isolated services (the second instance would collide): usedevsandbox port.
Agent instructions
Give every instance of my devsandbox sandbox <sandbox name> its own private Postgres and Redis, so parallel sessions never share data.
- Read the devsandbox-cli and config-toml-spec skills first (load them if they are installed, otherwise read them from https://github.com/Nemikolh/devsandboxes/tree/main/skills). Follow them over your own assumptions: unknown config keys are hard errors.
- Find my devsandbox config dir: the folder holding devsandboxes.toml, passed to devsandbox as
-C <config dir>. If you cannot tell which one, ask me. - Add
[services.postgres]and[services.redis]without ascope(isolated), with images matching the versions the repo targets andPOSTGRES_PASSWORDinenv. No hostports. - List both in the sandbox's
servicesand set the connection variables the repo reads (e.g.DATABASE_URL,REDIS_URL) incontainerEnv, with hostspostgresandredis. - Install in
postCreateCommandand mount its host config dir (its login) into the container. - Validate with
devsandbox -C <config dir> lsand fix every error it reports before going on. - Start two instances with
devsandbox -C <config dir> run <sandbox name> --name <task>and checkdevsandbox -C <config dir> statslists a postgres and a redis for each. - Run the migrations in one instance and confirm the other's database is untouched; check
devsandbox -C <config dir> exec <task> --versionworks. - Ask me before anything destructive: devsandbox rm, gc, rebuild --force, service rebuild, deleting files or branches.
Source: site/src/content/examples/isolated-services.mdxEdit this page on GitHub(opens in a new tab)