Build Once. Promote Forward. Ship Daily.
originally posted at LinkedIn at December 12, 2025
Eight years ago—before I had “DevOps” in my title—I ran into a release process that felt… unnecessarily painful.
We built a Docker image for dev and ran tests. Then we rebuilt for staging and ran the same tests. Then we rebuilt again for production and ran the same tests again.

At first it looked “safe.” In practice it was slow, expensive, and frustrating. It also produced multiple artifacts to store and track, even though the code hadn’t changed. And that’s the part that kept bothering me: if we build three times, are we really shipping the same thing?
Back then, I didn’t have control over the pipeline, so I filed the thought away and moved on. But I never forgot it.
Fast forward to Flagler. When I was asked, “What can we improve?”, that old idea came back immediately—and this time I had the opportunity to make it real.
This post is the story of what we changed, why it worked, and how it helped us go from shipping every two weeks to shipping daily.
The hidden cost of rebuilding per environment
“Rebuild per stage” is one of those patterns that sneaks into organizations quietly. It’s often a reasonable starting point: each environment has its own configuration, its own secrets, its own rules. So the pipeline grows stage by stage, until rebuilding becomes “just how it’s done.”
But once you look closely, it carries a few big problems.
It’s slow in the most painful place
Rebuilding and re-testing doesn’t just add time—it adds time right where humans are waiting. The work is done, the change is approved, and now you’re watching a pipeline crawl through repeated steps that don’t create new value.
It multiplies artifacts and complexity
If each stage produces its own image tag, you end up with more storage, more scanning events, and more “which image is actually deployed?” conversations than you’d like to admit.
It creates room for “almost the same” releases
Even when application code doesn’t change, rebuilds aren’t always identical. Base images update. Package repositories change. Dependency resolution changes. A minor timing difference changes a layer, which changes a scan result, which changes everything.
And that leads to the worst kind of failure: the kind that makes everyone feel helpless.
The security scan loop that broke everyone’s patience
In a previous job, we had a policy: every image had to be security scanned. Totally reasonable.
But the workflow was built around rebuilding in each stage. And that’s where it got ugly.
We’d finish scanning the staging image… then rebuild for production… and the production scan would fail.
Not because the app changed. Because the world around the build changed.
Now we’re stuck. The fix wasn’t “promote staging to prod.” The fix was “rebuild everything again,” starting from dev.
So we’d run the loop again. And there was no guarantee we wouldn’t hit the same failure again, because the build inputs were still drifting under our feet.
That’s the kind of process that drains teams:
- engineers lose confidence in releases
- people start delaying deployments
- frustration becomes normal
It wasn’t anyone’s fault. The system was just designed in a way that made this inevitable.
The lesson I took from that experience was simple:
If you rebuild three times, you’re validating three different artifacts.
And you’re leaving yourself exposed to randomness.
The shift: build once, promote forward
At Flagler, when I was asked what we could improve, I finally had the chance to revisit the idea that had been sitting in my head for years:
Stop rebuilding the same artifact in every environment.
Instead:
- Build the image once
- Test it once
- Scan it once
- Promote that exact same image through environments
We tag our images with the git short SHA (for example, app:1a2b3c4). That tag becomes the “identity” of the artifact that passed CI.
Promotion is then a controlled change to point each environment at the same artifact.
The big mindset change is this:
- environments are deployment targets
- they shouldn’t be build targets
Build and test answer: “Is this artifact valid?”
Promotion answers: “Where should this validated artifact run next?”
Why Argo CD makes this click
Once you adopt promotion, Argo CD becomes a force multiplier.
Instead of having a long pipeline do heavy work at each stage, the workflow becomes:
- build + validate once
- update the environment configuration to reference the same image tag
- Argo CD syncs and deploys
So promotion becomes a small Git change, not a “run the whole world again” event.
And that changes the pace of delivery.
What changed in the real world
This wasn’t just a pipeline optimization. It changed how shipping feels.
Promotions went from hours to minutes
Previously, moving a feature through environments meant waiting on repeated rebuilds and repeated test runs. Now it’s closer to: update a reference, Argo syncs, done.
The release “event” disappeared
When releases are slow and heavy, teams batch changes. When releases are fast and reliable, teams ship smaller changes more often.
We went from biweekly to daily shipping
By removing redundant rebuild + re-test loops, and by treating promotion as a GitOps action, we shortened the path from “ready” to “deployed” enough that shipping daily became normal.
Not heroic. Not stressful. Normal.
The advantages, plainly
Here’s what we gained by building once and promoting forward.
Reliability: the same artifact in every environment
If staging is running app:1a2b3c4, production runs app:1a2b3c4. Not “the same code rebuilt later,” but the same artifact.
That one detail eliminates a surprising amount of chaos.
Faster feedback and faster delivery
Less waiting, fewer repeated steps, fewer opportunities for a pipeline to fail for reasons unrelated to the change.
Reduced operational noise
Fewer artifacts. Clearer traceability. Easier debugging when something goes wrong, because you can answer “what changed?” without guesswork.
A better security story
Scanning is most meaningful when it’s tied to a specific artifact that you actually deploy. Promotion aligns security validation with reality: the scanned thing is the shipped thing.
The human part: trust and flexibility
This kind of change is technical, but it isn’t only technical.
It takes trust, because you’re changing a ritual people rely on, even if it’s painful. I’m grateful to my boss for the flexibility and confidence to let me push this through and prove it out.
Closing
Eight years ago, I saw rebuild-per-environment pipelines and wondered why we accepted them as normal. I didn’t have control then. At Flagler, I finally did.
Build once. Validate once. Promote forward.
And once we did, daily shipping stopped being an aspiration and became a habit.
If you’ve lived through “it passed in staging but failed in production” rebuild loops—especially around security scans—I’d love to hear what patterns helped you break out of it.