Skip to content
Skillv1.0.0

notion-rate-limits

Manage Notion API rate limits with exponential backoff, queue-based throttling, and batch optimization. Use when hitting 429 errors, implementing retry logic, or optimizing API request throughput for

by jeremylongshore(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from jeremylongshore/tons-of-skills-marketplace (skills/.curated/notion-rate-limits/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill notion-rate-limits. Copyright stays with the author (MIT).

Notion Rate Limits

Overview

The Notion API enforces 3 requests per second per integration token across all endpoints and tiers. Exceeding this returns HTTP 429 with a Retry-After header. Detect with isNotionClientError() + APIErrorCode.RateLimited, implement exponential backoff with jitter, and use queue-based throttling for high-throughput workloads.

Prerequisites

  • @notionhq/client v2.x (TypeScript) or notion-client (Python)
  • Integration token in NOTION_TOKEN from notion.so/my-integrations
  • For queue patterns: p-queue v8+ (npm install p-queue)

Instructions

Step 1 — Detect Rate Limits and Apply Exponential Backoff

Aspect Value
Rate limit 3 req/s per integration token (all tiers)
Throttle response HTTP 429 + Retry-After header (seconds)
Scope Per token, not per user or workspace
Max block children 1,000 per blocks.children.append
Max page size 100 results per paginated request

The SDK retries 429 automatically (2 retries, 3 total attempts). For heavier workloads, use custom backoff that honors Retry-After and adds jitter to prevent thundering herd:

import { Client, isNotionClientError, APIErrorCode } from '@notionhq/client';

const notion = new Client({ auth: process.env.NOTION_TOKEN });

async function withBackoff<T>(
  fn: () => Promise<T>,
  maxRetries = 5, baseMs = 1000, maxMs = 32_000
): Promise<T> {
  for (let i = 0; i <= maxRetries; i++) {
    try { return await fn(); }
    catch (err) {
      if (i === maxRetries) throw err;
      if (isNotionClientError(err) && err.code === APIErrorCode.RateLimited) {
        const wait = parseInt((err as any).headers?.['retry-after'] ?? '1', 10);
        await new Promise(r => setTimeout(r, wait * 1000));
        continue;
      }
      if (isNotionClientError(err) && err.status && err.status < 500) throw err;
      const delay = Math.min(baseMs * 2 ** i + Math.random() * 500, maxMs);
      await new Promise(r => setTimeout(r, delay));
    }
  }
  throw new Error('Exhausted retries');
}

Step 2 — Throttle with Queue-Based Request Management

Enforce the 3 req/s limit at the application level instead of relying on 429 responses:

import PQueue from 'p-queue';

const queue = new PQueue({
  concurrency: 3, interval: 1000, intervalCap: 3,
  carryoverConcurrencyCount: true,
});

async function throttled<T>(fn: () => Promise<T>): Promise<T> {
  return queue.add(fn, { throwOnTimeout: true }) as Promise<T>;
}

// Fetch 50 pages — automatically throttled to 3/s
const pages = await Promise.all(
  pageIds.map(id => throttled(() => notion.pages.retrieve({ page_id: id })))
);

Step 3 — Optimize Batch Operations to Minimize API Calls

Set page_size: 100 on every paginated query. Batch block appends into chunks of 100 instead of one-per-block. See batch patterns for full implementations with progress tracking.

// Paginate with max page size
async function queryAll(dbId: string, filter?: any) {
  const results = [];
  let cursor: string | undefined;
  do {
    const resp = await throttled(() => notion.databases.query({
      database_id: dbId, page_size: 100, start_cursor: cursor, filter,
    }));
    results.push(...resp.results);
    cursor = resp.has_more ? resp.next_cursor ?? undefined : undefined;
  } while (cursor);
  return results;
}

Output

  • 429 errors retried automatically using Retry-After headers with jitter
  • Queue-based throttling keeps requests at 3/s proactively
  • Batch operations reduce total API calls via chunking and max page_size

Error Handling

Scenario Strategy
Single 429 Honor Retry-After, retry once
Repeated 429s Exponential backoff + reduce concurrency
Bulk ops (50+ items) Queue with p-queue at 3 req/s
Server error (5xx) Backoff + retry up to 5 attempts
Client error (4xx) Do not retry — fix the request

Examples

See full TypeScript and Python examples for database sync, bulk export, and rate limit monitoring patterns.

Resources

Next Steps

  • See notion-common-errors for 401/403/404 troubleshooting alongside rate limits
  • See notion-sdk-patterns for query patterns that work with these strategies
  • See notion-search-retrieve for optimizing search to reduce API call volume

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/jeremylongshore-tons-of-skills-marketplace-notion-rate-limits/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

jeremylongshore-tons-of-skills-marketplace-notion-rate-limits.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-notion-rate-limits",
  "kind": "skill",
  "name": "notion-rate-limits",
  "description": "Manage Notion API rate limits with exponential backoff, queue-based throttling, and batch optimization. Use when hitting 429 errors, implementing retry logic, or optimizing API request throughput for Notion integrations. Trigger with \"notion rate limit\", \"notion 429\", \"notion retry\", \"notion backoff\", \"notion throttling\", \"notion too many requests\", \"notion queue\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "saas",
      "productivity",
      "notion",
      "rate-limiting",
      "api",
      "resilience",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Manage Notion API rate limits with exponential backoff, queue-based throttling, and batch optimization. Use when hitting 429 errors, implementing retry logic, or optimizing API request throughput for Notion integrations. Trigger with \"notion rate limit\", \"notion 429\", \"notion retry\", \"notion backoff\", \"notion throttling\", \"notion too many requests\", \"notion queue\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "skills/.curated/notion-rate-limits/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/skills/.curated/notion-rate-limits/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/skills/.curated/notion-rate-limits/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit,",
      "Bash(npm:*),",
      "Glob,",
      "Grep"
    ],
    "license": "MIT"
  },
  "instructions": "# Notion Rate Limits\n\n## Overview\n\nThe Notion API enforces **3 requests per second per integration token** across all endpoints and tiers. Exceeding this returns HTTP 429 with a `Retry-After` header. Detect with `isNotionClientError()` + `APIErrorCode.RateLimited`, implement exponential backoff with jitter, and use queue-based throttling for high-throughput workloads.\n\n## Prerequisites\n\n- `@notionhq/client` v2.x (TypeScript) or `notion-client` (Python)\n- Integration token in `NOTION_TOKEN` from [notion.so/my-integrations](https://www.notion.so/my-integrations)\n- For queue patterns: `p-queue` v",
  "cost": {
    "context_tokens": 1214
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-notion-rate-limits/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.