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.
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).
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.