| name | notion-reliability-patterns |
| description | Graceful degradation when Notion is down: offline cache, retry with exponential backoff, circuit breaker, health checks, and fallback content. Use when building fault-tolerant Notion integrations for production, or when a Notion outage is breaking your app. Trigger with phrases like "notion reliability", "notion circuit breaker", "notion offline fallback", "notion health check", "notion graceful degradation".
|
| allowed-tools | Read, Write, Edit |
| version | 1.38.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| tags | ["saas","productivity","notion"] |
| compatibility | Designed for Claude Code |
Notion Reliability Patterns
Overview
Production reliability patterns for Notion integrations: retry with exponential backoff, a circuit breaker to prevent cascade failures, and graceful degradation (offline cache, health checks, fallback content) so users see stale data instead of errors when the API is unreachable. All patterns use Client from @notionhq/client and handle Notion-specific error codes.
The three layers compose in order — retry sits inside the circuit breaker, which sits inside the cache/fallback layer. Read the skeletons below to follow the workflow, then open references/implementation.md for the complete copy-paste code.
Prerequisites
@notionhq/client v2.x installed (npm install @notionhq/client)
lru-cache for in-memory caching (npm install lru-cache)
- Python:
notion-client installed (pip install notion-client)
NOTION_TOKEN environment variable set
- Understanding of circuit breaker and retry patterns
Authentication
All patterns authenticate with a Notion internal integration token read from the NOTION_TOKEN environment variable — new Client({ auth: process.env.NOTION_TOKEN }) (TS) or Client(auth=os.environ["NOTION_TOKEN"]) (Python). Never hardcode the token; the health check calls notion.users.me() to confirm the token is valid and the API reachable.
Instructions
Build the three layers in order. Each skeleton shows the shape; the full implementation lives in references/implementation.md.
Step 1: Retry with Exponential Backoff
Classify errors as transient (429, 500, 502, 503, timeouts, network) vs permanent (400/401/404), retry only the transient ones with exponential backoff + jitter, and honor the Retry-After header on rate limits.
async function retryWithBackoff<T>(fn: () => Promise<T>, opts = {}): Promise<T> {
}