Primary Error All articles
Opinion

Your App Doesn't Need a Faster Algorithm. It Needs to Stop Exploding.

Primary Error
Your App Doesn't Need a Faster Algorithm. It Needs to Stop Exploding.

Photo: software engineer looking stressed at computer with system error alert, via i.pinimg.com

Here's a scenario that's probably familiar: a senior engineer spends two weeks optimizing a critical service. They profile it, benchmark it, rewrite the hot path, and ship something genuinely impressive — 40% faster, cleaner memory usage, the works. Three weeks later, an unexpected null from a third-party API cascades through that beautifully optimized code and brings down a feature for six hours.

The algorithm was excellent. The error handling was three nested try-catch blocks and a generic Exception e at the bottom that logged a message and moved on.

This is the pattern I want to talk about — because it's everywhere, and it's costing teams far more than any algorithmic inefficiency ever would.

We've Collectively Decided Exceptions Are Embarrassing

There's a cultural thing happening in software development where error handling gets treated as the ugly cousin of "real" engineering work. Algorithms are interesting. Data structures are interesting. Distributed systems design is interesting. Exception hierarchies? That's just plumbing.

So what happens? Error handling gets written at the end of a sprint when everyone's tired. It gets copy-pasted from Stack Overflow. It gets added reactively after something breaks in production. It becomes a graveyard of catch (Exception e) { log.error("something went wrong"); } blocks that technically compile and technically do something.

This is a primary error — and I mean that literally. The mistake isn't in the core logic. It's in the assumption that the core logic is all that matters.

The Algorithm Obsession Is Understandable, But Misaligned

I get why this happens. Computer science education is heavily weighted toward algorithmic thinking. Big-O notation, sorting algorithms, tree traversals — these are what get tested, what get discussed in interviews, what feel like the intellectual core of the discipline.

Error handling doesn't have that prestige. It's not on LeetCode. Nobody's asking you to design a custom exception hierarchy on a whiteboard.

But here's the reality of production systems: your O(n log n) sort is never going to be the thing that pages you at 2 AM. A null pointer from an API that changed its response schema without warning, a database connection pool that silently exhausted, a third-party webhook that started sending malformed JSON — that's what pages you at 2 AM. And if your error handling isn't thoughtful, those edge cases don't just fail — they fail loudly, propagatively, and expensively.

Graceful Degradation Is a Design Choice, Not an Accident

The companies that get this right treat error handling as a first-class architectural concern. That means a few concrete things.

First, they define failure modes before they write happy-path code. What happens when the payment processor times out? What happens when the recommendation engine is unavailable? What happens when user data is partially corrupted? These aren't afterthoughts — they're requirements. The error path is as designed as the success path.

Second, they build custom exception hierarchies that reflect the domain. A generic RuntimeException tells you almost nothing. A PaymentGatewayTimeoutException that extends TransientPaymentException that extends PaymentException tells you exactly what happened, gives you structured handling at the right level of abstraction, and makes it trivially easy to distinguish "retry this" from "fail permanently and alert someone."

Third, they distinguish between recoverable and unrecoverable errors in the architecture itself. Not every exception should be treated the same way. A network blip is different from a data integrity violation. Catching them the same way — or worse, catching everything the same way — means you're flying blind.

What Getting It Wrong Looks Like

Let's be concrete. A SaaS company with a multi-tenant architecture had a background job that processed data exports for customers. The error handling strategy was essentially: catch anything that goes wrong, log it, mark the job as failed, move on.

One day, a bug introduced a resource leak that wasn't immediately obvious. The job would start, hit an error partway through, get caught, get logged, get marked failed — and leave a partially held database connection behind. Over time, under load, those leaked connections accumulated. Eventually, the connection pool exhausted. Now the error wasn't just affecting export jobs — it was affecting every feature that touched the database. A background job failure had cascaded into a full platform outage.

The fix wasn't hard once they found it. But the architectural lesson was expensive: swallowing exceptions without understanding their resource implications is its own kind of bug. Errors need to be handled, not just caught.

What Getting It Right Looks Like

Contrast that with how mature teams approach this. Netflix's chaos engineering culture — deliberately injecting failures to test resilience — is the famous example, but the underlying principle is accessible to teams of any size: assume failure will happen, design for it explicitly, and verify that your error handling actually does what you think it does.

At a more tactical level, a well-structured exception strategy means:

None of this is exotic. All of it requires treating error handling as something you design rather than something you bolt on.

The Uncomfortable Reframe

Here's the opinion I'll plant my flag on: for most production systems at most companies, investing engineering time in a robust error handling architecture will deliver more reliability than the same time spent on algorithmic optimization.

That's not an argument against caring about performance. It's an argument for honest prioritization. If your system handles errors gracefully, degrades predictably, and fails in ways that are recoverable and diagnosable — you have a system that works for users even when things go sideways. If your system is highly optimized but fails catastrophically at unexpected edge cases, you have a system that's impressive in demos and unreliable in production.

The algorithm is the thing you're proud of. The error handling is the thing that determines whether you're proud at 2 AM or on the phone with your on-call rotation.

Design both. But if you're honest about where the gaps are, you probably know which one needs more attention.

All Articles

Related Articles

You're Not Debugging Wrong, You're Thinking Wrong

Fencepost Mistakes That Burned Down the House: Off-by-One Errors in the Wild

Fencepost Mistakes That Burned Down the House: Off-by-One Errors in the Wild

When One Wrong Character Costs More Than Your Entire Engineering Budget

When One Wrong Character Costs More Than Your Entire Engineering Budget