The Build That Never Got Faster
# The Build That Never Got Faster
Friday evening.
A developer pushed what looked like the smallest change of the week.
One line of code.
No new dependencies.
No package updates.
The CI pipeline kicked off, and everyone expected the build to finish in a couple of minutes.
Instead...
15 minutes. Again.
Someone joked, "Did npm release another thousand packages?"
Another engineer restarted the pipeline.
Still 15 minutes.
A third build.
Still painfully slow.
Nothing had changed.
Yet every build behaved as though the project had been cloned from scratch.
The war room shifted from curiosity to frustration.
Logs revealed the familiar culprit:
npm install
Downloading.
Resolving.
Installing.
Every.
Single.
Time.
But why?
Nobody had touched package.json.
Nobody had updated package-lock.json.
Docker was supposed to cache dependency layers. That was the entire point.
Someone finally opened the Dockerfile.
At first glance, it looked perfectly normal.
Then one innocent-looking line quietly explained the entire mystery.
COPY . .
RUN npm install
Hidden inside the build context was a tiny file named build-timestamp.txt, regenerated during every CI run.
That single changing file altered the checksum of the entire COPY . . layer.
Docker assumed everything after it had changed too.
Its cache wasn't broken.
It was simply doing exactly what it had been told.
Every build discarded perfectly reusable layers and rebuilt dependencies from scratch.
The fix took minutes.
Copy dependency files first.
Run dependency installation once.
Copy application source afterwards.
Suddenly the pipeline looked very different.
A code-only change skipped dependency installation entirely.
Build times dropped from fifteen minutes to just a few.
Then the team pushed optimization even further.
BuildKit cache mounts preserved npm downloads between builds instead of fetching packages repeatedly. Remote cache registries allowed distributed runners to share cached layers, eliminating wasted work across CI agents. Dependency locking through package-lock.json ensured identical dependency trees, making cache reuse both predictable and reliable.
The biggest surprise wasn't that Docker caching failed.
It never failed.
The Dockerfile simply prevented it from helping.
Production engineering is full of incidents like this—where performance problems aren't caused by expensive infrastructure or complex bugs, but by a single misplaced instruction hiding in plain sight.
At InfraThrone, we recreate these production-grade scenarios because real DevOps isn't about memorizing Docker commands. It's about understanding why systems behave the way they do, uncovering hidden inefficiencies, and learning the design patterns that keep CI/CD pipelines fast, scalable, and predictable long before they become tomorrow's engineering bottleneck.
Discussion
to read and post comments.