Temporal Retry Policy Standards
Intermediate
Define retry policy standards for Temporal activities — backoff configuration, maximum attempts, non-retryable errors, and retry budget management for resilient workflows.
File Patterns
**/workflows/****/activities/**
This rule applies to files matching the patterns above.
Rule Content
rule-content.md
# Temporal Retry Policy Standards
## Rule
All activities MUST have explicit retry policies with appropriate backoff, maximum attempts, and non-retryable error classification.
## Format
```typescript
retry: {
initialInterval: "1s",
backoffCoefficient: 2,
maximumInterval: "1m",
maximumAttempts: 5,
nonRetryableErrorTypes: ["BusinessLogicError"],
}
```
## Requirements
### 1. Default Retry Policy
```typescript
// Standard retry policy for most activities
const defaultRetry = {
initialInterval: "1s",
backoffCoefficient: 2,
maximumInterval: "30s",
maximumAttempts: 5,
};
```
### 2. Retry Policies by Error Type
```typescript
// Transient errors: retry aggressively
const transientRetry = {
initialInterval: "500ms",
backoffCoefficient: 2,
maximumInterval: "10s",
maximumAttempts: 10,
};
// External API errors: retry with backoff
const apiRetry = {
initialInterval: "2s",
backoffCoefficient: 3,
maximumInterval: "2m",
maximumAttempts: 5,
};
// Infrastructure errors: retry longer
const infraRetry = {
initialInterval: "5s",
backoffCoefficient: 2,
maximumInterval: "5m",
maximumAttempts: 20,
};
```
### 3. Non-Retryable Errors (MUST define)
```typescript
const { processPayment } = proxyActivities({
startToCloseTimeout: "30s",
retry: {
...defaultRetry,
nonRetryableErrorTypes: [
"InvalidInputError", // Bad data — retrying won't help
"InsufficientFundsError", // Business rule — needs human action
"AuthorizationError", // Permission issue — needs config fix
"NotFoundError", // Resource doesn't exist
"DuplicateError", // Already processed
],
},
});
```
### 4. Activity Error Classification
```typescript
// In activity code: throw specific error types
import { ApplicationFailure } from "@temporalio/activity";
export async function processPayment(orderId: string, amount: number) {
try {
return await paymentGateway.charge(orderId, amount);
} catch (error) {
if (error.code === "INSUFFICIENT_FUNDS") {
// Non-retryable: throw ApplicationFailure
throw ApplicationFailure.nonRetryable(
"Insufficient funds",
"InsufficientFundsError",
{ orderId, amount }
);
}
// Retryable: let the error propagate naturally
throw error;
}
}
```
## Retry Budget Guidelines
| Activity Type | Max Attempts | Initial Interval | Max Interval |
|---------------|-------------|-------------------|--------------|
| API call | 3-5 | 1-2s | 30s |
| Database | 5-10 | 500ms | 10s |
| File I/O | 3-5 | 1s | 30s |
| Email/SMS | 5-10 | 5s | 2m |
| Payment | 3 | 2s | 30s |
## Anti-Patterns
- No retry policy (activity fails permanently on first error)
- Retrying non-retryable errors (insufficient funds, invalid input)
- Too many retry attempts without maximum (retry for days)
- No backoff coefficient (hammering a failing service)
- Same retry policy for all activity types
## Enforcement
Define shared retry policy constants. Require nonRetryableErrorTypes for all payment and business-logic activities. Review retry configuration in PRs.FAQ
Discussion
Loading comments...