Guide

Control Throughput

Throughput control is the operating plan for keeping webhook delivery inside the capacity of the systems that receive it.

Use this guide when providers send bursts, a destination has a strict rate limit, a deploy makes a receiver slow, or retries could turn one outage into a second traffic spike.

The goal is not to hide traffic or drop useful events. The goal is to accept ingress reliably, shape outbound delivery, hold only the affected routes, and replay deliberately after the receiver is healthy.

What You Are Controlling

FastHook separates inbound acceptance from outbound delivery. A source can keep receiving provider traffic while each connection decides whether, when, and how quickly a destination should receive routed events.

That split gives you several places to reduce pressure before the receiving service fails. Destination rate limits shape final delivery, while connection pause holds newly routed events before they are dispatched.

  • Source acceptance: whether the inbound webhook was accepted or rejected.
  • Connection routing: whether a source event should become a delivery event for one destination.
  • Connection rules: filters, transformations, delays, deduplication, and retry behavior.
  • Destination capacity: the maximum delivery rate a receiver can safely handle across every connection that targets it.
  • Held work: events with HOLD status waiting for a paused connection to resume.
  • Recovery operations: pause, unpause, retry, and bulk retry after an incident.
Use the narrowest control first: filter noise, pace the destination, pause only the affected route, then replay deliberately.

Control Levers

Start with the narrowest control that solves the pressure problem. Filtering noisy events is better than delivering them slowly. Rate limiting a fragile destination is better than letting it fail and relying on retries. Pausing a single connection is better than stopping an entire source.

  • Filters remove events that a destination does not need.
  • Destination rate limits cap sustained delivery to a receiver.
  • Retry backoff prevents temporary failures from becoming immediate retry storms.
  • Pause and unpause let you hold one route during maintenance or incidents.
  • Bulk retry replays only the failed traffic you select after the receiver is fixed.
  • Metrics show whether pressure is coming from new ingress, failed delivery, retry traffic, or held events.

Set Destination Capacity

If a receiving API has a known limit, encode that limit on the destination. This protects the receiver regardless of which source or connection sends traffic to it.

Pick a value the receiver can sustain during normal operation, not the highest number it can survive for a few seconds. Leave headroom for provider retries, deploys, database latency, and other application work.

FastHook enforces destination limits at send time. When capacity is exhausted, delivery is scheduled for a later slot instead of being recorded as a failed attempt.

In the current Structured Connections UI, edit the destination and enable Max delivery rate. The UI writes config.rate_limit and config.rate_limit_period on the destination.

  • A destination rate limit is shared by all connections that deliver to that destination.
  • Use per-second limits for tight API budgets and per-minute limits for smoother services.
  • Keep production, staging, and local CLI destinations separate because they usually have different capacity.
  • Rate-limited events appear as scheduled work until their delivery slot opens.
  • The Structured Connections UI currently exposes second, minute, and hour periods; the API reference also lists day.
  • The CLI update command uses PATCH /destinations/:id and merges the provided config with the existing destination config.
  • Include url, path, method, or auth settings only when you want to change them.
Max delivery rate is destination configuration, not a connection rule.
Destination rate limit
{
  "config": {
    "rate_limit": 120,
    "rate_limit_period": "minute"
  }
}

fasthook destinations update des_xxx --json-file destination-rate-limit.json

Filter Before Delivery

The cheapest event is the one you never send to a destination that does not need it. Put filters on the connection that feeds the constrained receiver.

This is especially useful for providers that send many event types to one source, while one service only cares about a small subset.

  • Filter on stable fields such as event type, provider account, path, or mode.
  • Avoid filtering on fields that are optional or known to change between provider versions.
  • For fan-out, add the filter only to the connection whose destination should receive less traffic.
Connection filter
{
  "rules": [
    {
      "type": "filter",
      "body": {
        "type": "invoice.paid"
      },
      "headers": {
        "stripe-signature": { "$exists": true }
      },
      "path": {
        "$starts_with": "/stripe"
      }
    }
  ]
}

fasthook connections update web_xxx --json-file billing-filter.json

Make Retries Gentle

Retries are recovery tools, but aggressive retries can multiply load while a receiver is already degraded. Use exponential backoff for failures that are likely to recover, and keep retry counts deliberate.

Include 429 when the receiver uses rate limiting. Include 5xx ranges for temporary server errors. Do not retry status codes that mean the payload is permanently invalid.

  • Short intervals are useful for brief network blips.
  • Longer intervals protect receivers that need time to drain queues or recover databases.
  • Retry rules are connection rules. The retry count is the number of retry attempts after the first delivery attempt.
  • If the receiver is returning a persistent 4xx, fix the payload or destination config instead of retrying.
Retry rule
{
  "rules": [
    {
      "type": "retry",
      "strategy": "exponential",
      "interval": 30000,
      "count": 5,
      "response_status_codes": ["429", "500-599", "!501"]
    }
  ]
}

fasthook connections update web_xxx --json-file retry-backoff.json

Pause One Route During Incidents

Pause a connection when one receiver is unhealthy but the source should keep accepting webhook traffic. Paused connections hold newly routed events for that route and can be unpaused when the receiver is ready.

Pause is not an emergency stop for work that has already been claimed by delivery workers. Use a conservative destination rate limit and watch event status while the route drains.

Disable a connection when the branch should stop receiving future events without building a backlog. That is a different operational choice.

  • Pause during planned maintenance, receiver deploys, database migrations, and known downstream outages.
  • Keep sibling connections running when only one destination is affected.
  • Retry a failed event only after the paused connection has been resumed; event retry does not bypass pause controls.
  • Before unpausing, confirm the receiver is healthy and its rate limit is low enough to handle the drain.
Incident controls
# hold delivery for one destination branch
fasthook connections pause web_xxx

# inspect pressure while the receiver recovers
fasthook events count --destination_id des_xxx --status failed
fasthook metrics events --destination_id des_xxx --from 2026-05-25T00:00:00Z --to 2026-05-25T23:59:59Z

# resume delivery when the receiver is healthy
fasthook connections unpause web_xxx

Recover With Targeted Replay

After an outage, replay the traffic that actually failed. Avoid replaying every request from the provider if only one destination branch failed.

Use Events and Attempts to narrow by source, destination, connection, status, time window, and retry context. Then create a single retry or a bulk retry for that slice.

Event retry targets one existing connection branch, so the connection must be enabled and unpaused. Request retry replays the original inbound request through current routing, filters, and pause state.

  • Retry events when the destination branch failed.
  • Retry requests when you need to run the accepted inbound request through routing again.
  • Resume a paused connection before starting single or bulk event retry for that route.
  • Make receivers idempotent before replaying large windows of business events.
Before bulk retry, set a pressure budget and watch the destination until the failed window drains.
Replay
# replay one failed routed event
fasthook events retry evt_xxx

# create a bulk retry from a narrow filter
{
  "type": "event_bulk_retry",
  "filter": {
    "destination_id": "des_xxx",
    "status": "failed",
    "from": "2026-05-25T10:00:00.000Z",
    "to": "2026-05-25T10:30:00.000Z"
  }
}

fasthook events bulk-operations create --json-file event-retry-window.json

Watch The Right Signals

Throughput problems usually show up as a shape, not a single number. Compare inbound request volume, event statuses, retry traffic, and destination attempts over the same time range.

  • Request spikes mean the producer sent more traffic than usual.
  • Failed event spikes mean a receiver, destination config, or network path is failing.
  • Retry spikes after a deploy often mean the receiver is rejecting or timing out on the new payload path.
  • HOLD events indicate paused delivery. SCHEDULED events can indicate retry backlog, delay rules, or rate-limited delivery.
  • One unhealthy destination should not hide healthy sibling routes in a fan-out topology.
Metrics and inspection
fasthook metrics requests --source_id src_xxx --from 2026-05-25T00:00:00Z --to 2026-05-25T23:59:59Z
fasthook metrics events --destination_id des_xxx --from 2026-05-25T00:00:00Z --to 2026-05-25T23:59:59Z
fasthook events list --destination_id des_xxx --status failed --limit 50
fasthook attempts list --event_id evt_xxx

Shared Destination Capacity

Because rate_limit belongs to the destination, it is shared by every connection that targets that destination. This matters for fan-in and for reuse of one receiver across several providers.

If two producers can burst into the same receiver, size the destination limit for their combined traffic. If one producer needs an isolated budget, create a separate destination record for that receiver endpoint or add stricter filters and pause controls on that producer's connection.

  • Fan-in branches that point to the same destination share one rate limit.
  • A bulk retry from one connection can consume capacity that another connection also needs.
  • Separate destinations give separate delivery budgets, even when URLs are similar.
  • Filters and pause controls remain connection-local and can protect one producer branch.
A shared destination has one shared delivery budget.

Scenario: Provider Burst

A provider sends a short burst after a campaign, incident, or bulk import. Your source should keep accepting traffic, but one destination may not need every event or may need slower delivery.

  • Confirm request volume with request metrics filtered by source.
  • Add or tighten connection filters for destinations that only need a subset.
  • Set or lower destination rate limits for the constrained receiver.
  • Use retry backoff for 429 and temporary 5xx responses.
  • Watch event metrics by destination until failed and held counts return to normal.

Scenario: Receiver Outage

A downstream service returns 5xx responses or times out after a deploy. The fastest safe response is usually to isolate that route, keep accepting ingress, and replay after the service is fixed.

  • Pause only the affected connection when the receiver cannot safely accept more traffic.
  • Keep other connections from the same source running if their destinations are healthy.
  • Inspect failed attempts to confirm whether the failure is status code, timeout, local fetch, auth, or payload shape.
  • Fix the receiver or destination config before creating large retries.
  • Unpause with a conservative destination rate limit, then bulk retry the failed window if needed.

Checklist

  • Every production destination has a known safe delivery rate.
  • Noisy providers are filtered before low-value events reach constrained receivers.
  • Retry rules use backoff and only retry recoverable status codes.
  • Operators know when to pause a connection instead of disabling it.
  • Paused connections are resumed before event retries or event bulk retries are started.
  • Bulk replay filters are narrow enough to avoid resending unrelated traffic.
  • Metrics are checked by source, destination, connection, status, and time window.
  • Receivers are idempotent so replay and retry traffic is safe.

Next