Memory is the constraint
Idle boxes are the largest single source of memory on the host, which is why a workspace outside the board's active column is stopped after half an hour of quiet, and why previews stop when idle.
Hosting
One container per workspace on your server. Each branch deploys to where you said it runs.
One container per workspace, on a host you control. Connect AWS and switch on what it may build, with a preflight before anything is switched on. Or point it at a VPS you already rent.
Previews stay on DevBench compute, free and throwaway. Test, staging and production go wherever you point each branch, and a workspace can mix them: staging on a rented box, production in an AWS account.
Where should it run?
DevBench compute
The container preview, as a named environment. Free, and open to everybody, because it is the test loop the whole team works in.
What you need
What DevBench does
Who may press it
Anyone can deploy a preview.
An agent may deploy a preview and never an environment: devbench deploy in a box never names one.
$ devbench deploy
Deploy this workspace's repos as live test containers. The same as the Deploy button.
DevBench is a control plane you run yourself, on a machine with Docker. Your code is cloned onto that host and leaves it only when you deploy it somewhere.
Outside
Your host · A machine with Docker
Leaves the host
Control plane · Django REST API
A Django REST API with token auth for the web, desktop and mobile clients, and Postgres behind it. Served over ASGI with Redis, so the chat's WebSockets are answered across workers; on WSGI everything still works, and every client quietly falls back to polling.
Idle boxes are the largest single source of memory on the host, which is why a workspace outside the board's active column is stopped after half an hour of quiet, and why previews stop when idle.
The first organization is seeded by its owner; everyone after joins with an invite code. There is no sign-up path that creates an organization.
The agent login every workspace shares is one setting in the organization. Which model answers is your choice, and nothing else on the host depends on it.
The agent brings the whole repo set up as containers you can click through, with the shared database and each repo's seed variables. Throwaway, free, reaching nobody: replaced by the next deploy, stopped when idle.
Under it, one row per branch says where that branch really runs. Each repo gets a step timeline with elapsed times, and the log pane follows the build.
Throwaway, free, reaching nobody. Replaced by the next deploy, stopped when idle.
The Deploy tab has two halves. Preview runs the workspace's whole repo set as containers on DevBench compute. Environments is one row per branch, saying where that branch actually runs.
DevBench does not deploy this. The row is the team's record of an environment somebody else's pipeline builds; its URL, login and notes are editable by anyone on the workspace.
The container preview, as a named environment. The shared database and each repo's seed variables, replaced by the next deploy, stopped when idle, reaching nobody. Free, and open to everybody, because it is the test loop the whole team works in.
A static site in S3 behind CloudFront, an EC2 or Lightsail instance, a machine of your own over SSH. Staging on a rented box and production in an AWS account is two rows with different targets.
A disconnected account, a capability nobody switched on, or an IAM policy missing a permission comes back as a sentence in the response to the button, not as a deployment that fails ninety seconds after you have walked away.
DevBench records what it made, bucket and prefix, distribution id, instance id, and the next deploy overwrites that site and reuses that distribution and that instance. Recreating a distribution means a new domain and a quarter-hour of propagation; recreating an instance doubles the bill and leaves the old one serving the old code.
For a published site, a box you own or an instance, Stop marks the deployment stopped and touches nothing. A button in a list is not consent to take a production site off the internet.
An unknown target raises. It never falls back to DevBench compute; a deployment landing somewhere other than where its environment says is the thing this design removes. A failed deploy to an environment reaches the owners' Inbox, throttled per environment. A failed preview does not; you are looking at it.
Deploying to a machine, over SSH or onto an instance DevBench just created, runs an update script your team writes, on the environment. An environment without one is refused by name rather than guessed at.
DevBench did not build that box and cannot know whether the app is behind systemd, pm2, docker compose or a Makefile, and every wrong guess restarts something in production.
set -euo pipefail # DevBench adds this line cd /srv/app git fetch origin "$DEVBENCH_BRANCH" git checkout -q "$DEVBENCH_BRANCH" git pull --ff-only npm ci && npm run build sudo systemctl restart app # yours: systemd, pm2, compose, make…
The host key is pinned. The first connection records the fingerprint; a changed one is refused.
The script runs under set -euo pipefail, so a failed git pull stops rather than restarting a service with the old code still on disk.
It is fed to bash on stdin rather than quoted into a command line.
$DEVBENCH_BRANCH, $DEVBENCH_REPO, $DEVBENCH_REPO_URL, $DEVBENCH_ENVIRONMENT, $DEVBENCH_PROJECT and $DEVBENCH_DEPLOYMENT are exported, so one script serves every environment.
AWS
Credentials say who DevBench is in an account; feature toggles say what it may build there. The two halves are kept deliberately separate, and a connection belongs to the organization, not to the person who pasted it.
Credentials can be a plain IAM user's keys, or keys whose only right is to assume a role in the target account, the usual arrangement when one management account fans out to several. A capability whose required settings are still blank cannot be switched on at all.
That capability's declared actions are evaluated against the calling principal's actual policies, performing none of them.
Normal for a tightly scoped deploy user. A read-only probe runs instead and the result is recorded as a warning, never as ok. “The service answered” is a weaker claim than “the account is allowed”.
The page turns them into a pasteable IAM policy for whoever has the access, who is usually not the person looking at the screen.
A failure marks the account and reaches the owners' Inbox, throttled per account, with the throttle cleared the moment it recovers. Keys that start authenticating as a different AWS account bypass the throttle entirely. An account whose last check failed contributes no deploy targets, so a picker never offers something that cannot be reached.
Resources lists what already exists in the account. Linking a resource to the part of a repo it serves is how DevBench knows this Amplify app serves web/ and that EC2 box houses services/api.
$ devbench cloud can
What this workspace may do in the cloud, and how far.
$ devbench cloud list
Deployments that already exist in the organization's cloud accounts.
$ devbench cloud link <id> <repo>[/<dir>]
Record which part a resource serves.
$ devbench cloud call <service> <Operation>
One AWS call through DevBench. No credentials are ever given to a box.
A machine at Hetzner or Contabo with two cores and 4 GB costs a few euros a month, less than an EC2 instance a third its size. DevBench deploys onto it the same way it deploys onto an instance it created.
Any machine you can reach over SSH
Connecting asks forHost, port, user, a key or a password
The account machines come from
Connecting asks forA workspace API token
The account machines come from
Connecting asks forA personal access token
The account machines come from
Connecting asks forAn API key
A Supabase workspace
Connecting asks forWorkspace URL, service role key, anon key
Atlas or your own mongod
Connecting asks forA connection string
Verifying an SSH connection opens a session and reads the distribution, kernel, CPU count, memory and free disk. Each capability is checked by running the tool and asking for its version.
Every capability also needs systemd, because that is how services are installed and restarted. A missing package refuses the toggle and returns what is absent with the command that installs it, which the app turns into a shell script: the counterpart of the generated IAM policy, for the same reason. Whoever has root on the box is usually not the person looking at the screen.
The SSH provider takes a machine that already exists. The vendor-API providers take the account machines come from, which is what makes choosing a size and a region at deploy time possible. Every connection is re-verified on a schedule, and a failure reaches the owners.
Apps
An App is the set of repositories that make up one application. It is the unit a person picks when creating a workspace, and the unit a deployment resolves: deploy a frontend and the rest of its App comes up too. A repo belongs to at most one App.
Each part of an App, a repo or a directory inside a monorepo, carries its own recipe: the install, build and start commands, a port, what kind of thing it is (frontend, backend, worker), a Dockerfile path or a static output directory, and which secrets it needs. Write these by hand, or have DevBench read the repo in a throwaway box and propose them. Nothing is written until you apply the proposal.
Apps also own databases and their seed SQL, the data a preview boots with. The seed editor loads the stored SQL before showing you a box, because an empty box saved over a real dump is unrecoverable. A schema change belongs in a migration, not in the seed.
$ devbench deploy
Deploy this workspace's repos as live test containers. The same as the Deploy button.
$ devbench deploy config list
Every deployable part of this workspace and where it goes.
$ devbench deploy config generate
Read a repo in a throwaway box and propose how each part builds and runs.
$ devbench deploy config apply <id>
Turn a proposal into real deploy configs.
$ devbench deploy config set <repo>[/<dir>] --start … --build …
Create or edit one part's recipe.
$ devbench deploy seed set --file <path>
Replace a deploy database's seed. For schema changes, add a migration instead.
Invite only
Tell us about your team and the repositories you would bring; we reply within a working day.