DEV Community

Cover image for Why Retry Is One Of The Most Dangerous Keywords In Software
Amrishkhan Sheik Abdullah
Amrishkhan Sheik Abdullah

Posted on

Why Retry Is One Of The Most Dangerous Keywords In Software

Few lines of code look more innocent than this:

retry(3)
Enter fullscreen mode Exit fullscreen mode

It feels responsible.

Professional.

Resilient.

After all, networks fail.

Servers become unavailable.

Databases occasionally time out.

Retrying seems like the obvious solution.

And sometimes it is.

But after enough years building production systems, I've become convinced of something:

Retry is one of the most dangerous keywords in software.

Not because retries are bad.

Because retries amplify everything.

Good systems become more reliable.

Bad systems become disasters.

The problem is that many developers treat retries as a reliability feature when they're actually a distributed systems feature.

And distributed systems are where simple ideas go to become complicated.


Why Retries Exist

Imagine:

await fetch("/api/users");
Enter fullscreen mode Exit fullscreen mode

The request fails.

Maybe:

  • Network hiccup
  • Temporary database issue
  • Load balancer restart
  • Service deployment

The operation might succeed if attempted again.

So we write:

retry(3)
Enter fullscreen mode Exit fullscreen mode

Seems reasonable.

And in many cases:

It Works
Enter fullscreen mode Exit fullscreen mode

Which is why retries become popular.


The Dangerous Assumption

Most developers unconsciously assume:

Failure
=
Operation Did Not Execute
Enter fullscreen mode Exit fullscreen mode

Unfortunately that's not always true.

A request can:

Execute Successfully
↓
Response Never Arrives
Enter fullscreen mode Exit fullscreen mode

From the client's perspective:

Failure
Enter fullscreen mode Exit fullscreen mode

From the server's perspective:

Success
Enter fullscreen mode Exit fullscreen mode

Now a retry becomes dangerous.


The Double Payment Problem

Imagine a payment service.

await chargeCard(order);
Enter fullscreen mode Exit fullscreen mode

The card processor successfully charges:

$100
Enter fullscreen mode Exit fullscreen mode

The response is lost due to a network issue.

Client sees:

Request Failed
Enter fullscreen mode Exit fullscreen mode

and retries.

await chargeCard(order);
Enter fullscreen mode Exit fullscreen mode

again.

Now:

Charge #1 = Success
Charge #2 = Success
Enter fullscreen mode Exit fullscreen mode

The customer paid twice.

Nobody wrote bad logic.

The retry created the bug.


The Email Storm Problem

Consider:

await sendWelcomeEmail(user);
Enter fullscreen mode Exit fullscreen mode

Email provider accepts the message.

Response times out.

Application retries.

await sendWelcomeEmail(user);
Enter fullscreen mode Exit fullscreen mode

again.

Customer receives:

Welcome!
Welcome!
Welcome!
Welcome!
Enter fullscreen mode Exit fullscreen mode

Support ticket created.

Marketing team confused.

The retry succeeded.

Too well.


Retries Amplify Side Effects

This is the core issue.

Pure operations:

2 + 2
Enter fullscreen mode Exit fullscreen mode

can run forever.

Nothing changes.

Side effects are different.

Examples:

Charge Card
Create Order
Send Email
Book Seat
Reserve Inventory
Send SMS
Enter fullscreen mode Exit fullscreen mode

Each execution changes reality.

Retries repeat reality.

And reality doesn't always appreciate repetition.


The Thundering Herd Problem

One failed request isn't scary.

Ten thousand retries are.

Imagine:

Service A
Enter fullscreen mode Exit fullscreen mode

becomes slow.

Clients start retrying.

Traffic doubles.

Service becomes slower.

More retries occur.

Traffic doubles again.

Eventually:

Small Failure
↓
Massive Outage
Enter fullscreen mode Exit fullscreen mode

This is known as:

The Thundering Herd Problem
Enter fullscreen mode Exit fullscreen mode

And retries are often the cause.


When Retries Attack Databases

Suppose:

Database
Enter fullscreen mode Exit fullscreen mode

is under heavy load.

Queries start timing out.

Application retries automatically.

Now:

More Queries
↓
More Load
↓
More Timeouts
↓
More Retries
Enter fullscreen mode Exit fullscreen mode

You have accidentally built a denial-of-service attack against your own database.


Why Idempotency Matters

In the previous article we discussed:

Idempotency
Enter fullscreen mode Exit fullscreen mode

This is where it becomes critical.

Without idempotency:

Retry
=
Repeat Side Effects
Enter fullscreen mode Exit fullscreen mode

With idempotency:

Retry
=
Same Result
Enter fullscreen mode Exit fullscreen mode

A retry becomes safe.

That's why reliable systems almost always combine:

Retries
+
Idempotency
Enter fullscreen mode Exit fullscreen mode

rather than using retries alone.


Not Every Failure Should Be Retried

A common mistake:

retry(3)
Enter fullscreen mode Exit fullscreen mode

for every error.

Consider:

400 Bad Request
Enter fullscreen mode Exit fullscreen mode

Retrying won't help.

The request is invalid.

Or:

401 Unauthorized
Enter fullscreen mode Exit fullscreen mode

Retrying won't magically authenticate the user.

Good retry policies distinguish between:

Transient Failures
Enter fullscreen mode Exit fullscreen mode

and

Permanent Failures
Enter fullscreen mode Exit fullscreen mode

Exponential Backoff Exists For A Reason

Bad:

Retry Immediately
Retry Immediately
Retry Immediately
Enter fullscreen mode Exit fullscreen mode

Better:

1 Second
↓
2 Seconds
↓
4 Seconds
↓
8 Seconds
Enter fullscreen mode Exit fullscreen mode

This is:

Exponential Backoff
Enter fullscreen mode Exit fullscreen mode

and it prevents systems from overwhelming already struggling services.


Real World Example: Flight Booking

Imagine:

Reserve Seat
Enter fullscreen mode Exit fullscreen mode

times out.

Client retries.

Without protection:

Seat Reserved Twice
Enter fullscreen mode Exit fullscreen mode

or:

Two Different Seats Reserved
Enter fullscreen mode Exit fullscreen mode

Now inventory becomes inconsistent.

Airlines spend enormous effort preventing these scenarios.

Because retries happen constantly.


Real World Example: Webhooks

Webhook providers often retry automatically.

For example:

Payment Completed
Enter fullscreen mode Exit fullscreen mode

may arrive:

1 Time
2 Times
5 Times
Enter fullscreen mode Exit fullscreen mode

depending on delivery conditions.

Systems that assume:

Exactly Once
Enter fullscreen mode Exit fullscreen mode

processing usually fail eventually.

Systems that expect retries survive.


Real World Example: Message Queues

Kafka.

RabbitMQ.

SQS.

Azure Service Bus.

All assume:

Messages May Be Delivered Again
Enter fullscreen mode Exit fullscreen mode

because reliability is more important than uniqueness.

Consumers must be designed accordingly.


Common Retry Mistakes

Retrying Everything

Not every failure is recoverable.


Retrying Immediately

Often makes outages worse.


Ignoring Idempotency

Creates duplicate side effects.


Infinite Retries

Eventually becomes infinite damage.


Hiding Failures

Retries should not become a substitute for monitoring.


Pros Of Retries

1. Better Reliability

Transient failures disappear.

2. Better User Experience

Temporary outages become invisible.

3. Improved Resilience

Systems tolerate instability.

4. Reduced Manual Intervention

Many failures self-heal.

5. Better Distributed Systems

Network failures become manageable.


Cons Of Retries

1. Duplicate Operations

Without idempotency.

2. Traffic Amplification

Can worsen outages.

3. Cascading Failures

One issue spreads across systems.

4. Increased Complexity

Backoff strategies become necessary.

5. Hidden Production Problems

Retries can mask deeper issues.


The Real Lesson

Most developers think retries exist to make software more reliable.

That's only partially true.

Retries don't eliminate failures.

They change failures.

Sometimes they transform:

Temporary Network Problem
Enter fullscreen mode Exit fullscreen mode

into:

Duplicate Payment
Enter fullscreen mode Exit fullscreen mode

Sometimes they transform:

Slow Database
Enter fullscreen mode Exit fullscreen mode

into:

Full System Outage
Enter fullscreen mode Exit fullscreen mode

That's why experienced engineers don't ask:

Should We Retry?
Enter fullscreen mode Exit fullscreen mode

They ask:

What Happens If This Operation Executes Twice?
Enter fullscreen mode Exit fullscreen mode

Because once retries enter the picture, duplicate execution is no longer an edge case.

It's a certainty.

And reliable systems are designed with that reality in mind.


What's Next?

In the next article we'll discuss:

The Myth Of Stateless Systems

Because many systems described as "stateless" are actually storing state somewhere else.

And that distinction turns out to be extremely important.


About The Author

Hi, I'm Amrish Khan.

I enjoy building developer tools, exploring software architecture, and writing about the deeper ideas behind everyday programming concepts.

I'm also building Aruvix — a growing ecosystem of local-first developer tools designed to process data directly in the browser without unnecessary uploads.

Here's a detailed blog on Aruvix:

https://dev.to/amrishkhan05/aruvix-the-ultimate-offline-first-developer-toolkit-e0i

You can follow my work and thoughts here:

Portfolio:
https://www.amrishkhan.dev

LinkedIn:
https://www.linkedin.com/in/amrishkhan

GitHub:
https://www.github.com/amrishkhan05

If you enjoyed this article, consider following for more deep dives into JavaScript, architecture, local-first software, and performance engineering.

Top comments (0)