Backend error handling shapes how systems respond when things go wrong—whether that's a database timeout, an invalid request, or a cascading infrastructure failure. Resilient backends don't just catch errors; they recover from them, communicate clearly, and fail gracefully when recovery isn't possible. This cheat sheet covers structured response formats, retry patterns, circuit breakers, fallback mechanisms, and observability strategies that turn brittle systems into self-healing ones. One key insight: distinguish transient errors (worth retrying) from permanent errors (requiring immediate attention) — retrying permanent errors wastes resources and delays user feedback, while abandoning transient errors loses legitimate requests.
What This Cheat Sheet Covers
This topic spans 16 focused tables and 91 indexed concepts, 90 flashcards. Below is a complete table-by-table outline of this topic, spanning foundational concepts through advanced details.
A jump-to index of every table row in this cheat sheet.
An interactive map of every table and concept in this topic.
Table 1: Error Response Structure Patterns
How you shape an error response decides how easily clients can react to it. A consistent, machine-readable body—whether the RFC 7807 Problem Details standard or your own coded JSON envelope—lets callers branch on an error code instead of scraping prose, surface every validation failure at once, and trace an issue back through a correlation ID. The recurring discipline: be specific and helpful in development, but strip stack traces and internals before they reach production clients.
| Pattern | Example | Description | |
|---|---|---|---|
{"type":"https://api.com/errors/validation", "title":"Validation Failed", "status":400, "detail":"Email is invalid", "instance":"/users/123"} | • Standardized JSON format for HTTP API errors • includes machine-readable type URI, human-readable title, HTTP status, detailed message, and request identifier | ||
{"error":{"code":"INVALID_INPUT", "message":"Email required", "field":"user.email", "timestamp":"2026-05-16T14:22:14Z"}} | • Consistent JSON structure with application error code, message, affected field, and timestamp • enables programmatic error parsing | ||
{"errors":[ {"field":"email","message":"Invalid format"}, {"field":"age","message":"Must be 18+"}]} | • Returns all validation errors at once rather than one at a time • allows clients to fix multiple issues in a single iteration | ||
{"error":"Internal server error", "correlationId":"9d2dee33-7803-485a-a2b1", "timestamp":"2026-05-16T14:22:14Z"} | • Unique identifier linking error response to distributed trace • enables end-to-end request tracking across microservices for debugging | ||
{"success":false, "data":null, "error":{"code":"NOT_FOUND","msg":"User not found"}} | • Wraps all responses in consistent structure with success flag, data payload, and error object • simplifies client-side response handling | ||
HTTP 409{"code":"DUPLICATE_EMAIL", "message":"Email already exists"} | Combines standard HTTP status (409 Conflict) with application-specific error code for fine-grained client handling. | ||
{"error":"Database timeout", "stack":"at getUserById (user.go:42)..."} | • Includes full stack trace in development/staging environments • must be excluded in production to prevent leaking implementation details | ||
{"error":"INVALID_INPUT", "message":"Email is invalid", "message_es":"El email es inválido"} | • Provides error messages in multiple languages using Accept-Language header or explicit locale parameter • improves international UX |