The Plumbing Hell #
Distributed systems are great for scale. For the developer trying to write code on a Tuesday afternoon, they’re often a nightmare.
I call it “Plumbing Hell.” To run a single service locally, you spin up Kafka, Postgres, Redis, and three other microservices. You write 500 lines of docker-compose.yaml or try to run a full Kubernetes cluster on your laptop just to verify an API change. You spend more time managing ports, debugging container networking, and waiting for the environment to stabilize than you do writing actual code.
We’ve normalized this. We shouldn’t have.
Intent vs. implementation #
The core problem: our tools conflate intent (what I want to happen) with implementation (how it happens).
When I say “I need a Postgres database,” I shouldn’t have to manually map ports to localhost:5432 or write a Kubernetes StatefulSet just to run a test. The intent is clear. The implementation should be the tool’s problem, not mine.
That’s the motivation behind bs.
What bs is
#
The No Bullshit Build System. An artifact-centric build orchestrator written in Go.
The philosophy: define intent, let the system handle plumbing. You write a bs.yaml describing your architecture. bs acts as a Translator — it reads that intent and produces environment-specific instructions:
- Local dev: direct Docker API calls, hot-reloading, no k8s overhead.
- Production: Kubernetes manifests or Helm charts from the same source of truth.
You don’t write Docker Compose files. You don’t maintain separate configs per environment. You describe what you need, and the Translator figures out how to run it.
Key design decisions #
The Translator pattern #
bs decouples service definition from execution. The same bs.yaml produces different outputs for dev, test, and prod. The developer’s mental model stays the same regardless of where the code runs.
Auto-wiring and secrets #
One of the biggest friction points in local dev is configuration sprawl. If Service A depends on a database, bs doesn’t just inject a connection URL — it provisions environment variables, API keys, and TLS certificates at runtime. No .env copy-pasting, no hardcoded secrets.
Everything is an artifact #
In bs, even a database is an artifact. It can be pre-seeded with schema scripts, snapshotted, and cached as an immutable image. This means your local dev database is reproducible, not a snowflake that drifts over time.
Where it stands today #
To be clear: this is not a finished product. I’m deep in Phase 1, building the skeleton:
- Core CLI —
spf13/cobrafor the entry points - DAG engine — topological sort for parallel execution and dependency graphing
- Docker adapter — runtime interface talking directly to the Docker client
- Local store — content-addressable store (CAS) for build artifacts
This post is a statement of intent. I’m building the core to solve friction I face daily with microservice development, and I’ll post updates as each phase ships. If you’re drowning in plumbing too, the repo is on GitHub.