Staring at that stalled pull request, cursor blinking accusingly over two near-identical validation blocks. “Unify them,” demands the comment. Three hours later — you’re drowning in a generic function bloated with flags, if-statements, and edge-case hacks just for billing.
That’s the DRY principle ambush, right there in your daily grind. Don’t Repeat Yourself — gospel from the clean code crowd — but in microservices land, it’s often a fast track to brittle dependencies. I’ve chased this dragon; watched “shared utils” libraries turn deployments into minefields.
Remember the Shared Utils Debacle?
Back in the early 2010s, every team chased elegance. One date formatter for all services. Sounded smart — until tweaking it for auth nuked billing reports across the org. Dependencies hid everywhere, like landmines in a playground.
Here’s my unique twist, one the original rant misses: it’s Unix philosophy inverted. Unix favored small, duplicative tools that compose loosely — think grep here, sed there — over monolithic libraries. Microservices? Same vibe. Duplication lets services evolve independently, no central chokepoint begging for a rewrite.
And boy, does it scale. Copy-paste those five SMTP lines? Done. No unraveling a GenericEmailService tangled with marketing templates versus transactional blasts.
But — plot twist — un-abstracting is hell. Ever tried? Friday afternoons lost to if-else webs and Optional params. Duplication? Refactor in isolation, deploy at will.
I’ve lost count of how many PRs I’ve seen stalled because someone pointed out two similar-looking blocks of code and demanded they be “unified.” It sounds like a great idea until you’re three months deep into a “generic” validation function that now takes eight boolean flags just to handle one edge case in the billing service.
Spot on. Readability wins every time. Logic in plain sight — no hunting through nested helpers. Billing tweaks? Touch only billing. Inventory? Untouched.
Why Ditch the Rule of Three?
They say duplicate twice, abstract on the third. I wait till five, six times. Even then? Pause. Is it truly the same business logic, or coincidental similarity?
Take validation: user signup checks IDs one way; inventory stock another. Looks alike superficially — regex, null checks — but domains diverge fast. Abstract early? You’re coupling evolutions that shouldn’t touch.
In backends, I’d take ten duplicated lines over a 50-line utility juggling cases. Why? Change velocity. Delete a feature? Snip the dupe, gone. No codebase surgery.
Corporate hype calls this “technical debt.” Bull. Debt’s the abstraction regret pile I’ve accumulated. Duplication? Liberation.
Look, DRY shines low-level: math utils, crypto primitives, stable protocols. Business logic? Repeat away. It’s the price of agility.
Code reviews weaponize DRY worst. Easiest nitpick — “looks like that other thing” — skips architecture costs. Lazy dogma, ignoring how software mutates.
Is DRY Dead in Microservices?
Not dead — contextualized. In monoliths, maybe unify. Distributed systems? Duplication’s your decoupling superpower.
Prediction: as serverless rises, this flips harder. Ephemeral functions — duplicate logic deploys faster, scales without shared lib versioning woes. AWS Lambda teams already whisper this.
I’ve regretted zero duplications. Abstractions? Countless. Next PR pushback? “Show me the coupling risk.”
Shift your lens. Duplication isn’t slop; it’s intentional simplicity amid chaos.
🧬 Related Insights
- Read more: Why Perplexity and Burstiness Failed — And What Actually Catches AI Slop
- Read more: Claude Grades Gemini’s Homework: 50/100 and a Stern Lecture
Frequently Asked Questions
Is code duplication always okay?
No — reserve for business logic across domains. Low-level pure functions? DRY them.
When should I abstract code instead?
Only if it’s identical concepts (math, protocols) and changes rarely. Test the waters with three-plus dupes first.
Does this break clean code principles?
Clean code evolves. Prioritize readability and loose coupling over zero duplication.