Routing strategies overview
import { Aside } from ‘@astrojs/starlight/components’
When a webhook arrives at your Hookman endpoint, the proxy needs to decide which deployment to forward it to. This decision is called routing.
A project’s routing is a list of rules, each with a condition that reads part of the request. Hookman evaluates them in two tiers, by priority (lower first) within each tier:
Tier 1 Dynamic rules (registered by the CLI / GitHub Action)Tier 2 Manual rules (created in the dashboard) ↓ no rule matched Active deployment (the default target) + fan-out copies (mirrored to any fan-out deployments)A rule’s condition reads a header, a query param, or a JSON body field and matches it against a value. The first rule that matches wins, and the request goes only to that rule’s deployment. If no rule matches, the request falls through to the active deployment (plus fan-out — see below). If no rule matches and there’s no active deployment, Hookman returns 422 no_route_resolved.
Configuring routing
Set up routing in your project settings (dashboard or API). You can configure multiple strategies simultaneously — they’re evaluated in the order above.
Project settings → Routing ☐ Routing header: x-hookman-branch ☐ Query parameter: branch ☐ Payload path: metadata.branchLeave all three blank to use manual switch only.
Strategy comparison
| Header | Query param | Payload | Manual switch | |
|---|---|---|---|---|
| Requires body parse | No | No | Yes | No |
| Caller must include routing key | Yes | Yes | Yes | No |
| Works with any provider | Depends | Depends | Depends | Yes |
| Fully automatic | Yes | Yes | Yes | No |
Manual switch
The simplest strategy. You explicitly set which deployment receives webhooks by marking it as active. No routing key needed from the caller.
Good for: solo developers, prototyping, any situation where you want direct control.
Header routing
Hookman reads a specific request header and matches its value against your deployment labels.
Incoming header: x-hookman-branch: feature/checkoutDeployment label: feature/checkout→ Routes to that deploymentGood for: internal tooling, platforms that let you inject custom headers, webhook forwarders.
Header routing documentation →
Payload routing
Hookman parses the JSON body and reads a value at a dot-notation path.
// Incoming body{ "metadata": { "branch": "feature/checkout" } }
// Config: payload path = "metadata.branch"// Resolved value: "feature/checkout"// → Routes to matching deploymentGood for: platforms that include environment metadata in their payload (some CI platforms, internal event buses, custom webhook senders).
Payload routing documentation →
Dynamic rules
Rules registered by the CLI or GitHub Action are dynamic rules. They behave like any other rule but:
- They’re evaluated first (Tier 1), before any rules you create in the dashboard.
- They go live in KV immediately on registration — they don’t sit in a draft waiting for you to publish.
This is what makes hookman register from CI safe and instant: a preview branch starts receiving its routed webhooks the moment the action runs.
Fall-through and the default
Rules are tried in order. A rule that matches forwards the request to its deployment and stops. A rule that doesn’t match is simply skipped — Hookman moves to the next rule.
If no rule matches, the request goes to the active deployment (the default). If there’s no active deployment either, Hookman returns 422 no_route_resolved — the response includes a trace showing how each rule was evaluated.
Fan-out
Deployments can be marked fan-out. When a webhook falls through to the default (active) deployment, Hookman also mirrors a copy to every fan-out deployment.
no rule matched → active deployment (main) + fan-out deployment (staging) + fan-out deployment (teammate's branch)By default fan-out applies to the fall-through only — a webhook that matched a rule goes only to that rule’s deployment, and fan-out is skipped.
Individual rules can opt back in. Each rule has a fan-out toggle (the checkbox on the rule form, fanout on the API) meaning when this rule matches, still copy to the fan-out deployments as well as my own target:
matched a rule with fan-out off → that rule's deployment only
matched a rule with fan-out on → that rule's deployment (pr-42) + fan-out deployment (staging)A deployment that is both the resolved target and marked fan-out receives one copy, not two. Each fan-out delivery is logged and counts toward your monthly quota.