Skip to content
Skillv1.0.0

salesforce-rate-limits

Implement Salesforce API limit management, backoff, and quota monitoring. Use when handling REQUEST_LIMIT_EXCEEDED errors, implementing retry logic, or optimizing API request throughput for Salesforce

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/salesforce-rate-limits/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill salesforce-rate-limits. Copyright stays with the author (MIT).

Salesforce Rate Limits

Overview

Handle Salesforce API limits gracefully. Salesforce uses a 24-hour rolling limit (not per-minute), plus concurrent request limits and Bulk API quotas.

Prerequisites

  • jsforce connection configured
  • Understanding of your org's edition and license count
  • Access to Setup > Company Information

Instructions

Step 1: Understand Salesforce API Limits

Limit Type Calculation Example (Enterprise, 50 users)
Daily API Requests Base + (per-user * licenses) 100,000 + (1,000 * 50) = 150,000
Concurrent API (long-running) 25 per org 25
Bulk API 2.0 Ingest Jobs 15,000/day 15,000
Bulk API 2.0 Query Jobs 15,000/day 15,000
Composite Subrequests 25 per call 25
SOQL Query Row Limit 50,000 per query 50,000
sObject Collections 200 records per call 200

Key difference from most SaaS APIs: Salesforce limits are per-org, not per-user or per-key. All integrations sharing the same org share the same pool.

Step 2: Monitor Remaining Quota

import { getConnection } from './salesforce/connection';

async function checkApiLimits(): Promise<{
  used: number;
  remaining: number;
  max: number;
  percentUsed: number;
}> {
  const conn = await getConnection();
  const limits = await conn.request('/services/data/v59.0/limits/');

  const daily = limits.DailyApiRequests;
  const used = daily.Max - daily.Remaining;
  const percentUsed = (used / daily.Max) * 100;

  return {
    used,
    remaining: daily.Remaining,
    max: daily.Max,
    percentUsed: Math.round(percentUsed * 10) / 10,
  };
}

// Also available in every REST API response header:
// Sforce-Limit-Info: api-usage=135/150000

Step 3: Implement Backoff for REQUEST_LIMIT_EXCEEDED

async function withSalesforceRetry<T>(
  operation: () => Promise<T>,
  config = { maxRetries: 5, baseDelayMs: 2000, maxDelayMs: 60000 }
): Promise<T> {
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error: any) {
      const errorCode = error.errorCode || error.name;

      // Only retry on transient/limit errors
      const retryable = [
        'REQUEST_LIMIT_EXCEEDED',
        'SERVER_UNAVAILABLE',
        'UNABLE_TO_LOCK_ROW',
      ];

      if (attempt === config.maxRetries || !retryable.includes(errorCode)) {
        throw error;
      }

      // Exponential backoff with jitter
      const exponentialDelay = config.baseDelayMs * Math.pow(2, attempt);
      const jitter = Math.random() * 1000;
      const delay = Math.min(exponentialDelay + jitter, config.maxDelayMs);

      console.warn(`${errorCode}: retry ${attempt + 1}/${config.maxRetries} in ${Math.round(delay)}ms`);
      await new Promise(r => setTimeout(r, delay));
    }
  }
  throw new Error('Unreachable');
}

Step 4: Pre-Flight Limit Check

class SalesforceQuotaGuard {
  private warningThreshold = 0.8; // Warn at 80%
  private blockThreshold = 0.95;  // Block at 95%

  async canMakeRequest(estimatedCalls: number = 1): Promise<{
    allowed: boolean;
    remaining: number;
    reason?: string;
  }> {
    const { remaining, max, percentUsed } = await checkApiLimits();

    if (remaining < estimatedCalls) {
      return {
        allowed: false,
        remaining,
        reason: `Only ${remaining} API calls remain (need ${estimatedCalls})`,
      };
    }

    if (percentUsed / 100 >= this.blockThreshold) {
      return {
        allowed: false,
        remaining,
        reason: `API usage at ${percentUsed}% — blocking to preserve quota`,
      };
    }

    if (percentUsed / 100 >= this.warningThreshold) {
      console.warn(`API usage at ${percentUsed}% (${remaining} remaining)`);
    }

    return { allowed: true, remaining };
  }
}

Step 5: Reduce API Call Count

// STRATEGY 1: Use sObject Collections (1 call = 200 records)
// Instead of 200 individual creates...
const records = contacts.map(c => ({ FirstName: c.first, LastName: c.last, Email: c.email }));
await conn.sobject('Contact').create(records); // 1 API call, not 200

// STRATEGY 2: Use Composite API (1 call = 25 operations)
// See salesforce-core-workflow-b

// STRATEGY 3: Use Bulk API for 10K+ records (1 job = unlimited records)
// Bulk API has its own separate limit pool

// STRATEGY 4: Cache describe calls — metadata rarely changes
const describeCache = new Map<string, any>();
async function cachedDescribe(sObjectType: string) {
  if (!describeCache.has(sObjectType)) {
    describeCache.set(sObjectType, await conn.sobject(sObjectType).describe());
  }
  return describeCache.get(sObjectType);
}

// STRATEGY 5: Use queryMore for pagination (doesn't count as extra API call)
let result = await conn.query('SELECT Id, Name FROM Contact');
while (!result.done) {
  result = await conn.queryMore(result.nextRecordsUrl!);
  // Process result.records
}

Output

  • API limit monitoring with threshold alerts
  • Automatic retry with exponential backoff for limit errors
  • Pre-flight quota checks before batch operations
  • Strategies to reduce API call consumption

Error Handling

Error Code HTTP Status Meaning Action
REQUEST_LIMIT_EXCEEDED 403 Daily API limit exceeded Wait for 24hr window to reset
CONCURRENT_LIMIT_EXCEEDED 403 Too many concurrent requests Queue and throttle
SERVER_UNAVAILABLE 503 Salesforce temporarily down Retry with backoff
UNABLE_TO_LOCK_ROW 409-equivalent Record contention Retry with backoff

Examples

Throttle a bulk integration before quota exhaustion

Read the Limits REST resource at the start of each batch, reserve a safety margin agreed with other integrations, and reduce concurrency or defer non-urgent work when the margin is approached. Use exponential backoff with jitter only for transient failures, never for a hard daily quota exhaustion. Test the policy against sandbox limits with synthetic work, record the deferred batch identifiers, and resume only after a fresh quota check confirms capacity.

Resources

Next Steps

For security configuration, see salesforce-security-basics.

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-salesforce-ra-d72b48/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-salesforce-ra-d72b48.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-salesforce-ra-d72b48",
  "kind": "skill",
  "name": "salesforce-rate-limits",
  "description": "Implement Salesforce API limit management, backoff, and quota monitoring. Use when handling REQUEST_LIMIT_EXCEEDED errors, implementing retry logic, or optimizing API request throughput for Salesforce. Trigger with phrases like \"salesforce rate limit\", \"salesforce API limit\", \"salesforce 403\", \"salesforce retry\", \"salesforce governor limits\", \"API quota\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "saas",
      "crm",
      "salesforce",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Implement Salesforce API limit management, backoff, and quota monitoring. Use when handling REQUEST_LIMIT_EXCEEDED errors, implementing retry logic, or optimizing API request throughput for Salesforce. Trigger with phrases like \"salesforce rate limit\", \"salesforce API limit\", \"salesforce 403\", \"salesforce retry\", \"salesforce governor limits\", \"API quota\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "skills/.curated/salesforce-rate-limits/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/skills/.curated/salesforce-rate-limits/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/skills/.curated/salesforce-rate-limits/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit"
    ],
    "license": "MIT"
  },
  "instructions": "# Salesforce Rate Limits\n\n## Overview\n\nHandle Salesforce API limits gracefully. Salesforce uses a 24-hour rolling limit (not per-minute), plus concurrent request limits and Bulk API quotas.\n\n## Prerequisites\n\n- jsforce connection configured\n- Understanding of your org's edition and license count\n- Access to Setup > Company Information\n\n## Instructions\n\n### Step 1: Understand Salesforce API Limits\n\n| Limit Type | Calculation | Example (Enterprise, 50 users) |\n|-----------|-------------|-------------------------------|\n| Daily API Requests | Base + (per-user * licenses) | 100,000 + (1,000 * 50) ",
  "cost": {
    "context_tokens": 1681
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-salesforce-ra-d72b48/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.