dozeGitHubGet doze

A short history of local development

Your code used to run where you wrote it.

Then, one sensible decision at a time, it moved away.

The long way round.

Six stops. What each one really fixed, what it cost, and the way back home.

Stop one · Services and a READMEIt ran on your laptop.

A package manager, a few background services, and a README that said what to type. Postgres on 5432, because that's where Postgres goes.

Save the file, refresh the page. Between you and your running code: nothing at all.

Then a second project wanted a different Postgres, and a new hire's laptop didn't have one running at all.

The README knew one machine by heart: the one that wrote it.

Works on my machine. Exactly one machine.

What it fixed
Nothing in the way. Native speed, a debugger that just attached, logs in the terminal you started it from.
What it cost
It worked on one laptop. Versions drifted, services ran forever, and the setup lived in somebody's head.

Stop two · A VM per projectA computer inside the computer.

So each project got its own virtual machine, built from a file in the repo. The same OS and the same versions, for everyone, and no laptop got a vote.

Still your laptop, though: the VM runs on it. One command. Go and make a coffee. Possibly two.

It worked. It was also a whole operating system per project: memory reserved whether you used it or not, and a shared folder that sent every file read the scenic route.

Three projects, three computers, one lap.

What it fixed
Reproducible. The setup became a file in the repo instead of a page in a wiki.
What it cost
A whole operating system per project. Minutes to boot, a slow shared folder, and the first wall between you and your code.

Stop three · One compose fileOne file. Real wins.

Containers made the machine small and the file short. One compose file named the database, the cache, the queue and the apps, and one command brought them all up, the same for everyone.

This was a genuine step forward. For packaging and shipping software, it still is.

But on a Mac or a Windows laptop, a container means a Linux VM. The VM came back: smaller, always on, holding every service all day, used or not. The fan noticed.

Every file change crossed a mount. Reloads dragged, so web quietly moved back out to run on the laptop. Now the stack lived in two places, and you kept track of which.

Debugging meant publishing a port from inside the container and mapping source paths across the wall.

“Works on my machine” became “works in my container”.

What it fixed
One declarative file for the whole stack, pinned versions, a clean slate on demand. A real step forward.
What it cost
A VM in the middle again, always on. Slow mounts, debugging through a wall, and a fan that never stops.

Stop four · Kubernetes for devThen production became a cluster.

So development tried to look like it: a cluster on the laptop, inside the VM, inside the laptop. Nesting dolls, with YAML.

A chart of ten templates, to say hello world.

“It's just YAML,” said nobody twice.

Then the laptop gave up, and the stack moved out to a shared cluster: a namespace per developer.

For the first time on this trip, your running code is not on your laptop. What's left on your laptop is the editor, and a VPN.

Web came home to reload fast, again. Everything it talks to stayed in the cluster.

So every save is a sync and a rebuild somewhere else, and every database you want to look at is a port-forward back to your laptop. 5432 is still taken on this side.

The debugger waits on the tunnel. The tunnel waits on the debugger. The logs are in another tool, in another tab.

What it fixed
Development finally looked like production: the same manifests, the same networking, real service names.
What it cost
A cluster to learn before you can write a feature. Templates for a hello world, sync tools, a tunnel per port.

Stop five · Cloud dev environmentsThen the editor left too.

A dev box per developer, in the cloud. The editor in a browser tab, or attached over SSH. A fresh machine in minutes, the same for everyone.

Your laptop became a window onto somebody else's computer. On a train, the cursor runs a little behind your typing, as if it's thinking it over.

Your laptop became a very expensive Chromebook.

Every pull request got a preview environment of its own, billed by the hour until somebody closed it. And everyone shared one staging, which everyone, eventually, broke.

What it fixed
Onboarding in minutes. Big machines on demand, a clean environment every time, previews you can link in a review.
What it cost
Everything is a network hop away: lag on every keystroke, a bill by the hour, and nothing works offline.

Stop six · The platform teamA team to hold it all up.

Somebody has to run all of this. So there's a platform team, and they're good at it.

Between you and a new database: a ticket, a queue and a person.

Then quotas: your namespace is out of memory. On Thursday, a cost review for dev environments.

A new hire spends week one on access requests: the VPN, the cluster, the dev box, the secrets. Writing code is pencilled in for later.

Then #platform: Dev environments degraded. No ETA. The platform team is on a production incident first, as they should be. Nobody on your team can run anything.

Your AI agent can read every file in the repo. It can't reach the cluster either.

One of the walls is a person.

What it fixed
Somebody owns it. Paved roads, guardrails, security reviews, one way to do things.
What it cost
A team on call for your inner loop. Tickets for a database, quotas, cost reviews, and when it's down, nobody works.

Meanwhile.

On your desk sits the most powerful computer you have ever owned.

It's running a browser tab of a dev box, a chat app and a video call about the ETA. Mostly idle, except for the fan.

Every stop on the way fixed something real. None of them asked whether the laptop was the problem.

It wasn't. The problem was everything on it running at once, all day, with nothing to tell it to rest.

Local development didn't get fixed. It got moved.

The way home · dozeBring it home.

doze runs the whole stack on your machine as native processes. Postgres is a process. Your API is a process. One file in the repo, doze.hcl, says what runs and what it needs, and doze.lock pins the versions for everyone.

Here that's Larder, our made-up grocery example: real code, seven services in Go, Python and TypeScript, a gateway and a web shop, on Postgres, Valkey, Kafka and AWS.

doze up. Everything comes back. Between you and your running code: nothing, again. The receipt? Torn up.

Your laptop. Already paid for.

Everything sleeps until it's called. Two minutes with no connections and a service goes to sleep; the next connection wakes it. At rest it's one daemon: it held 27.1 MB on our Mac, and 1.3 MB more after 100,000 log lines (make bench).

And the app shows all of it: what's awake, what's asleep, and what woke what.

Your debugger attaches to a process on your own machine. A breakpoint just hits. No published ports, no path maps, no tunnel.

Need the real hostname for a sign-in callback? Give the app your own domain, over https: one line in the file and one admin prompt.

Your agent runs doze status and doze logs and sees what you see. Offline, on a train, during somebody else's outage: you keep working.

The platform team builds the platform: the deploy pipeline, production, the paved road. Not babysit dev boxes. Nobody's pager is part of your inner loop.

Containers and clusters stay where they shine: shipping and running production. They just don't have to be where you write code.

Evening. You close the lid.

Nothing's still running. The fan is off. You go home.

Every stop fixed something.
doze keeps the fixes, and drops the distance.

Services and a README
Native speed; your debugger just attached
Native processes, on your machine
A VM per project
The setup is a file in the repo
One doze.hcl in the repo
One compose file
The whole stack, declared, pinned
Every service declared; versions pinned in doze.lock
Kubernetes for dev
Real names instead of ports
A name for every service; your own domain over https
Cloud dev environments
A new machine is ready fast
git clone, doze up
The platform team
Somebody owns the paved road
They still do. Your inner loop just stops needing them.
The last stop6With doze0

walls between you and your running code. The story's own count; draw yours.

Work hard. Then close the lid.

Take the long way round again