Skip to content

Concurrency & Rate Limits

Concurrency key

Limit how many instances with the same key run simultaneously. Prevents running two campaigns for the same contact at once.

{
  "concurrency_key": "contact:john@acme.com",
  "max_concurrency": 1
}

Instances that exceed max_concurrency are deferred until a slot opens — they are never dropped.

Idempotency key

Prevent duplicate instance creation. If an instance with the same key already exists, the API returns the existing instance ID and "deduplicated": true.

{
  "idempotency_key": "signup:user-12345:2024-01-15"
}

Rate limiting

Per-resource sliding window, scoped by tenant. Overages are deferred — rescheduled to the next available slot, never dropped or failed.

// Set on the step that should be rate-limited
{
  "type": "step",
  "handler": "http_request",
  "params": { "url": "https://api.example.com/send", "method": "POST" },
  "rate_limit_key": "mailbox:outreach@acme.com"
}

// Rate limit configuration (created via API or config)
{
  "resource_key": "mailbox:outreach@acme.com",
  "max_count": 30,
  "window_seconds": 86400
}

Rate limit checks are atomic — a single database round-trip. Multiple scheduler nodes share the same rate limit counters via PostgreSQL.