Prompt
How do I debug retries causing duplicate API calls?
Latest observation
Retry-related duplicate API calls usually come from one of three places: the client retries, the server processes the same request twice, or the network/timeout behavior makes a successful call look failed.
Here’s a practical way to debug it.
1) Confirm where the retry is happening
Check logs on both sides:
- Client logs
- Request sent
- Timeout/error received
- Retry attempt number
- Server logs
- Request received
- Request processed
- Response returned
If the client says “timed out” but the server shows it processed the request, the client may be retrying a request that actually succeeded.
2) Add a unique request ID
Include an idempotency key or request UUID with every API call.
Example:
- Header:
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000 - Or:
X-Request-ID: ...
Log it everywhere:
- client send
- proxy/load balancer
- server receive
- downstream service calls
If the same ID appears multiple times, you’ve found a duplicate retry pattern.
3) Check retry configuration
Look for:
- automatic HTTP client retries
- SDK built-in retries
- proxy retries
- load balancer retries
- queue consumer redelivery
- job scheduler re-running tasks
Common causes:
- timeout too low
- retry on all 5xx and network errors
- retry on POST without idempotency protection
- multiple layers each retrying independently
4) Inspect timeouts and latency
A classic pattern:
- Client sends request
- Server processes slowly
- Client times out
- Client retries
- Original request eventually succeeds too
Fixes:
- increase client timeout
- optimize server latency
- use async processing where appropriate
- make the operation idempotent
5) Make the endpoint idempotent
For operations that create/update data:
- accept an idempotency key
- store the key with the result
- if the same key comes in again, return the previous result instead of repeating the action
This is the best defense against duplicate side effects.
6) Correlate at the infrastructure layer
If you have:
- API gateway
- reverse proxy
- load balancer
- service mesh
check whether any of them:
- retries upstream failures
- buffers requests
- replays on connection reset
Enable access logs and trace IDs there too.
7) Use tracing
Distributed tracing tools like:
- OpenTelemetry
- Jaeger
- Zipkin
- Datadog/APM
can show whether one incoming request becomes multiple downstream calls.
8) Reproduce with controlled failures
Try:
- simulate latency
- force a timeout
- kill the connection after server processes the request
- inject 5xx responses
Then observe whether the client retries and whether the server duplicates work.
9) Add duplicate detection in storage
If the API creates records, add a unique constraint on a natural key or idempotency key.
That way even if retries happen, the database prevents duplicate inserts.
10) Look for non-obvious retry sources
Sometimes duplicates come from:
- browser form resubmission
- mobile app background retry
- message queue at-least-once delivery
- cron job overlap
- human double-clicks
- load balancer health checks misrouted to app endpoints
Quick debugging checklist
- Add/request log a unique request ID
- Verify client retry policy
- Check server processing time vs client timeout
- Search logs for duplicate IDs
- Confirm proxy/LB/gateway retries
- Use tracing to see repeated downstream calls
- Make writes idempotent
- Add DB uniqueness protection
If you want, I can also give you:
- a step-by-step debugging playbook, or
- examples for Python / JavaScript / Java / Go clients and servers.