“We can’t run locally” is usually a design smell.
I’m a believer that, as an engineer, you should be able to run your software locally. But I hear it often: “We can’t run locally because of some reason.”
Sometimes it’s valid. There are architectures and platforms out there that prevent running locally. But more often than not, when it comes to backend distributed systems, it’s a design or implementation decision that nobody has challenged.
Why This Matters
Everyone these days is focused on speeding up software delivery.
Today, that generally means coding agents, AI tooling, and code generation.
But writing code faster doesn’t matter much if validating a one-line change takes an hour.
The speed of software delivery is often dictated by validation, not code generation.
The Problem with Shared Dev Environments
Many teams still rely on shared development environments as their primary way of validating changes.
That process usually looks something like this:
- Make a change
- Commit the change
- Push the branch
- Wait for a build
- Wait for a deployment
- Run tests
If everything goes well, you can validate your change. If a mistake was made, or something doesn’t work right, you have to fix it and start over.
The result is a slow feedback loop, which can sometimes influence behavior.
The more friction there is to validate a change, the larger that change becomes. If testing takes a long time, you will naturally focus on making sure everything is perfect before spending time validating.
Local Validation Influences Good Behavior
Compare the above process to one that uses a locally running service.
- Make a change
- Build
- Start the service
- Run tests
The process is dramatically shorter and, more importantly, faster. This encourages engineers to make smaller changes, test more frequently, iterate their implementations, and find mistakes earlier.
This all results in better software.
The Excuses
“My service depends on too many other services.”
Run the services you own locally. Mock the services you don’t.
“I need a database or message broker.”
Run those locally too. There’s very likely a Docker container for each of them.
“We use cloud services.”
This one can be harder, but emulators exist for some services. Other services might have a Dockerized open-source alternative. For those that don’t, you could mock them.
There will always be exceptions: mainframes, specialized hardware, or unique managed services.
But I find many teams jump straight to “we can’t run locally” before they’ve seriously explored how they could.
Running Local Doesn’t Mean Everything
You don’t need to recreate your entire production environment on a laptop, though if you can, go for it.
The goal is to validate your change without depending on a shared or non-local environment that takes forever to test against.
Local development isn’t about recreating production. It’s about creating enough of the environment to validate your change. If that means turning off some functionality or creating mock services, it might be worth it.
Why This Matters Even More Now
Validating changes quickly is becoming more important as teams adopt coding agents. An agent can generate code in seconds.
But if every iteration with your coding agent requires committing, pushing, building, deploying, and waiting, the feedback loop becomes the bottleneck.
Final Thoughts
Agents make mistakes. Humans make mistakes.
The faster you can validate a change, the faster you can correct those mistakes. That’s why local execution isn’t just a convenience.
It’s one of the most effective ways to shorten the feedback loop.