EXAMPLE 03
  • services
  • networking
  • agents

Private services per instance

Every instance gets its own Postgres and Redis, so agents never touch each other's data.


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.

Let your agent set this up

Config

devsandboxes.toml
[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 "
devsandboxes.toml
[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:

TERMINAL
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:

TERMINAL
devsandbox exec -it fix-login 
devsandbox exec -it add-search 
TERMINAL
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, start and rm.
  • devsandbox service rebuild redis recreates every running instance’s redis in place (services reference).
  • No host ports on isolated services (the second instance would collide): use devsandbox port.

Agent instructions

Prompt for your coding agentPaste into Claude Code, Codex or any agent with a shell.

Give every instance of my devsandbox sandbox <sandbox name> its own private Postgres and Redis, so parallel sessions never share data.

  1. 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.
  2. 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.
  3. Add [services.postgres] and [services.redis] without a scope (isolated), with images matching the versions the repo targets and POSTGRES_PASSWORD in env. No host ports.
  4. List both in the sandbox's services and set the connection variables the repo reads (e.g. DATABASE_URL, REDIS_URL) in containerEnv, with hosts postgres and redis.
  5. Install in postCreateCommand and mount its host config dir (its login) into the container.
  6. Validate with devsandbox -C <config dir> ls and fix every error it reports before going on.
  7. Start two instances with devsandbox -C <config dir> run <sandbox name> --name <task> and check devsandbox -C <config dir> stats lists a postgres and a redis for each.
  8. Run the migrations in one instance and confirm the other's database is untouched; check devsandbox -C <config dir> exec <task> --version works.
  9. Ask me before anything destructive: devsandbox rm, gc, rebuild --force, service rebuild, deleting files or branches.
fill in before sending Agent skills (opens in a new tab)

Source: site/src/content/examples/isolated-services.mdxEdit this page on GitHub(opens in a new tab)

MENU /
View on GitHub
EXAMPLES
All examplesEvery recipe on one page.Parallel coding agentsSeveral coding agents on one repo, fully isolated from one another.One shared PostgresOne development database for all your sandboxes and their instances.Private services per instanceEvery instance gets its own Postgres and Redis, so agents never touch each other's data.Shared package cachesNew sandboxes stop downloading the same packages again.ssh-agent and git pushAgents push over ssh with your host's keys, which never enter the container.Port forwarding on demandOpen a sandbox's dev server or database from your host, without restarting anything.Attach VS CodeOpen any instance in VS Code with one key.devcontainer FeaturesAdd Node, Rust or the GitHub CLI to any image, in TOML.Babysit pull requestsAn agent keeps your open PRs merged with their base, and pings you when it can't.Port a devcontainer.jsonTurn an existing devcontainer.json into a devsandbox config.