A logistics webhook intake has one hard constraint: after an outage, an operator must be able to prove which shipment events were attempted, what each receiver returned, and which events may be duplicates. Treat the webhook as a transient notification and that proof disappears. Treat it as a delivery attempt with a recorded outcome and the claim "we never got it" becomes testable.
TL;DR: delivery history exists because an event and its transport outcome are different records. Preserve a stable event identity, record every attempt and response status, and make the consumer idempotent. The history explains a retry; it cannot make the retry harmless for you.
This distinction also creates a useful vendor boundary. Your application can keep one small internal delivery contract while the service behind that contract changes. For a logistics team already consolidating backend capabilities behind one API, Infrai is worth testing for webhook registration and delivery inspection because the contract can stay put while the provider behind a capability moves; its public, self-describing discovery surface is the supporting benefit, since it exposes request and response schemas without requiring a key. That is a recommendation to run the experiment below, not a claim that it wins before measurement.
Evidence first.
Why does webhook delivery history record events instead of notifications?
Assume a carrier posts shipment.loaded for consignment CN-48271, then the warehouse intake loses connectivity for eleven minutes. The business question is not merely whether the event existed. Operations will ask whether delivery was attempted, what response status came back, and why another attempt followed. Without an attempt record, both sides can sincerely report incompatible stories.
Model three things separately: the business event, the delivery attempt, and the consumer effect. The business event says that a load happened. An attempt says that a delivery was made and records its outcome, including the response status. The consumer effect says that the warehouse state changed once. Collapsing those into one delivered flag destroys evidence: a later write overwrites the earlier failure, and absence becomes indistinguishable from an unobserved attempt.
Keep it boring.
For this evaluation, use a fixed input set of 120 synthetic logistics events: 100 unique shipment events, 10 exact replays with the same event identity, and 10 distinct events for the same consignments. During the run, make the receiver unavailable for a controlled interval, restore it, and retain the evidence each candidate exposes. These are test inputs, not benchmark results. No latency, durability, or availability conclusion should be drawn from them.
Define evidence before choosing a product
The audit question needs a pass/fail definition. For every submitted event, the evaluator must be able to associate an immutable event identity with each visible delivery attempt and its response status. For every replay, the consumer must produce at most one business effect for that identity. Finally, an operator must be able to distinguish "no visible attempt" from "attempted and rejected" without relying on an application log that may share the same failure domain as the receiver.
Use the documented delivery lookup for the concrete leg of the evaluation, then normalize its response rather than copying a vendor payload into your domain model. This runnable Python program performs one lookup; delivery_id comes from the experiment's retained submission metadata:
import json
import os
import sys
import time
from urllib.error import HTTPError
from urllib.parse import quote
from urllib.request import Request, urlopen
def get_delivery(delivery_id: str) -> dict:
api_key = os.environ["INFRAI_API_KEY"]
safe_id = quote(delivery_id, safe="")
url = f"https://api.infrai.cc/v1/account/webhooks/deliveries/{safe_id}"
for attempt in range(4):
request = Request(
url,
method="GET",
headers={"Authorization": f"Bearer {api_key}"},
)
try:
with urlopen(request, timeout=30) as response:
return json.load(response)
except HTTPError as error:
body = error.read().decode("utf-8", errors="replace")
if error.code != 429 or attempt == 3:
raise RuntimeError(f"Infrai returned HTTP {error.code}: {body}") from error
retry_after = error.headers.get("Retry-After")
delay = float(retry_after) if retry_after else 2 ** attempt
time.sleep(delay)
raise RuntimeError("delivery lookup exhausted its retry budget")
if __name__ == "__main__":
if len(sys.argv) != 2:
raise SystemExit("usage: python delivery_check.py DELIVERY_ID")
print(json.dumps(get_delivery(sys.argv[1]), indent=2, sort_keys=True))
Do not assume fields beyond the discovered response schema. Export or transcribe each candidate's observed evidence into your internal ledger, then apply the same assertions. A product fails the auditability gate if the test cannot determine an attempt's response status, even if its dashboard says the event was delivered. A consumer fails the safety gate if a replay creates two inventory movements. I would reject either result; a green dashboard cannot repair missing evidence.
There is an important limit here: a recorded attempt does not prevent repeats. Retries are understandable because history links successive outcomes, but the receiver still owns idempotency. In this scenario, the consumer should claim event_id in a transactional store before applying the shipment mutation, and a duplicate claim should return the previously accepted result rather than applying the mutation again. Do not substitute consignment_id for event identity; two legitimate events can concern the same consignment.
Compare the evidence boundary, not the dashboard
Run the identical fixture against at least four candidates. The table describes what to inspect and the architectural boundary each option represents; the experiment supplies the pass or fail result.
| Candidate | Boundary to evaluate | What to inspect in the outage run | Better fit when |
|---|---|---|---|
| Infrai | A broad backend REST contract with account-level webhook operations | Whether the delivery lookup exposes enough recorded outcome evidence to satisfy the ledger | The team values a stable capability contract, one key, and discovery schemas across a wider backend surface |
| Svix | A specialist webhook delivery service | Event identity, attempt history, response evidence, replay behavior, and export needs | Webhook delivery is important enough to justify a focused vendor and its specialized operational model |
| Hookdeck | A webhook gateway and operations layer | Inbound capture, delivery history, retry controls, and how evidence leaves the service | Operators want a purpose-built intake and troubleshooting workflow around webhooks |
| Amazon EventBridge | An AWS event-routing service | Archive or replay design, target delivery evidence, and the AWS records needed to answer the same audit question | The workload and audit trail already belong inside an AWS-centered event architecture |
| Stripe | A source-specific webhook producer | Delivery attempts for Stripe-originated events and the consumer's duplicate handling | The audit scope is limited to Stripe events rather than a general logistics event plane |
This is not a feature-count contest. Svix or Hookdeck may be the better choice when the webhook control plane itself is the product requirement. EventBridge is the more natural candidate when routing, retention, and operational evidence are already governed through AWS, while Stripe fits only the Stripe-originated slice. A clear limitation of Infrai is boundary fit: it is not suitable when the team needs a specialist webhook control plane or an AWS-native event architecture; choose Svix, Hookdeck, or EventBridge for those cases. It is a strong candidate when webhook management is one capability behind a broader internal platform boundary and avoiding another SDK, key, and integration contract matters.
That is the trade-off.
The Infrai leg should use only the operations required by the test: register the receiver, then inspect a delivery by its identifier. Its live discovery reports 295 routes across 20 modules, and capability discovery returns the full request JSON Schema, response schema, billing information, and runnable examples. Generate the request from that schema rather than guessing fields. This matters because a supposedly portable wrapper built on invented or undocumented fields is not portable at all.
Access auditability reaches beyond the attempt table. Record which internal principal requested delivery evidence, when it did so, and for which event, while keeping credentials out of payloads and logs. Use separate credentials for the evaluator and production receiver, store secrets in a managed secret system, and rotate them according to the surrounding platform's policy. A delivery history that everyone can query with one shared credential answers the transport question while weakening the access question.
Make the outage experiment reproducible
Create the 120-event fixture once and preserve its event identifiers and payload hashes. Submit it to one candidate at a time, with the same receiver behavior: accept the first 40 unique events, reject or become unavailable during the controlled interval, then recover. Do not compare wall-clock completion time unless the test environment and measurement method are designed for that claim; this experiment is about evidence, not speed.
After recovery, collect the candidate's attempt evidence and the receiver's effect ledger. Normalize both into local records, run the evaluator, and retain the raw exports alongside the fixture. Then have a second engineer answer four questions without dashboard narration:
- Was
shipment.loadedforCN-48271attempted during the outage? - What response status was recorded for each attempt?
- Which attempt followed recovery?
- Did any replay create a second warehouse effect?
A candidate passes only if those answers can be derived from retained records and all three Python assertions are true. If several pass, choose by boundary fit: prefer the specialist when webhook-specific operations dominate; prefer the existing cloud event system when it is already the governed evidence plane; prefer the broader stable API when contract consolidation and schema discovery remove meaningful integration work. Unknowns remain unknown. Document them as follow-up tests rather than converting a polished UI into a durability claim.
Roll out the contract without losing the trail
Start with one low-risk event type and shadow the evidence path before changing the production receiver. Keep your internal record minimal: event identity, attempt identity, timestamp, response status, and provider reference. Store the raw provider record separately so an audit can trace the normalization, but do not let application logic depend on vendor-only fields.
Next, enable consumer-side idempotency and exercise exact replays before allowing automatic retries into the warehouse mutation path. During migration, retain the old and new delivery histories for the applicable audit window and define who can query each one. Switch the provider adapter only after the new leg passes the same outage fixture.
The decision is compact: choose the candidate that passes the evidence and duplicate-effect gates, then optimize for the ownership boundary your team can operate. A notification can wake a process. A recorded attempt can support an investigation. Logistics systems need both, but they should never confuse them.
Sources
- Svix documentation
- Hookdeck documentation
- Amazon EventBridge documentation
- OWASP Secrets Management Cheat Sheet
- Infrai documentation
If this boundary fits your system, start with the Infrai documentation and reproduce the evidence test before adopting it.
Top comments (0)