Containers, Native, or Neither
Reproducibility and speed pull in opposite directions on a developer machine. What each approach costs, and the hybrid most teams end up with.
Analysis
The local environment question is usually argued as a preference. It is a trade-off between consistency and iteration speed, and the right answer depends on which of those is currently hurting.
Native
Tools installed directly on the machine.
Fastest iteration. No virtualisation layer, no filesystem translation, native file watching.
Best editor and debugger integration.
Divergence between machines, which produces the failures nobody can reproduce.
Setup is manual and decays, unless scripted and tested.
Containers
The application and its dependencies in a container.
Consistent across machines, which removes a class of problem entirely.
Matches production more closely.
Slower. Filesystem performance for bind mounts is poor on some platforms, and the gap is large enough to change how people work.
File watching and hot reload frequently degrade or stop working.
Debugging is harder, requiring port forwarding and configuration most people get wrong once.
Development containers
A container definition checked into the repository, understood by editors.
Setup becomes cloning and opening, which addresses the onboarding problem directly.
Consistent, with the editor inside the container so integration works.
Still carries the filesystem cost on some platforms.
Adds a rebuild step when the definition changes, which people forget and then debug for an hour.
Cloud development environments
The environment runs remotely; the editor connects to it.
Powerful machines, which matters for large builds.
Consistent and instantly available, with no local setup at all.
Warm caches on creation, which removes the cold first build.
Requires connectivity, and latency shows in every keystroke on a bad link.
Costs money continuously, and idle environments are pure waste unless they suspend.
Local files and tools are gone, which is a real adjustment.
The hybrid most teams reach
Application code native, for iteration speed.
Dependencies in containers — databases, queues, third-party services — where consistency matters and speed does not.
A container or cloud environment as a fallback for onboarding and for anyone whose machine will not cooperate.
This gets most of the consistency benefit at most of the native speed, and it is where teams end up after trying the pure versions.
Choosing
If the pain is "works on my machine": move toward containers.
If the pain is slow iteration: move toward native.
If the pain is onboarding: development containers or cloud environments.
If the pain is build capacity: cloud environments.
Measure before deciding. Time an incremental build and a test run in each candidate, on a real change, on the machines people actually have. The differences are frequently larger than expected and occasionally the opposite of what was assumed.
Whatever you choose
Pin versions, explicitly.
Test the setup path automatically, on a clean image.
Support one path well rather than three badly. A team maintaining native, container and cloud paths maintains none of them.
Let people opt out with a documented alternative, because someone always has a reason.
Timing the candidates
The comparison that should precede the argument, and it takes an afternoon.
Pick a real change, not a hello-world.
Time an incremental build in each candidate environment.
Time a focused test run.
Time a full setup from clean.
On the machines people actually have, including the architecture minority.
The differences are frequently larger than expected and occasionally the reverse of the assumption, which is why the measurement is worth the afternoon.
Supporting one path well
A team maintaining three environment options maintains none of them.
Pick the primary path and make it excellent: tested, documented, scripted.
Provide one fallback for people the primary does not suit.
Document the fallback as unsupported rather than pretending parity.
Measure which is used, and if the fallback dominates, the primary is wrong.
Resist adding a third, which is where the maintenance cost becomes unaffordable and every option becomes mediocre.