Connections

Route events from sources to destinations with filters and transforms.

Connections are the routing layer of hookstream. Each connection links a source to a destination and optionally applies a content-based filter and a JSONata transform before delivery.

What is a Connection?

A connection is a route: source → destination, optionally gated by filters and reshaped by a transform. When an event arrives at a source, hookstream evaluates every connection for that source. If the event matches a connection's filters, it's transformed (if configured) and dispatched to the destination's DeliveryScheduler DO.

graph LR
  S[Source] --> C1[Connection A<br/>filter + transform]
  S --> C2[Connection B<br/>filter + transform]
  S --> C3[Connection C<br/>no filter]
  C1 --> D1[Destination 1]
  C2 --> D2[Destination 2]
  C3 --> D3[Destination 3]

Fan-Out

A single source can own any number of connections, each pointing at a different destination. One inbound webhook can trigger deliveries to many endpoints — and because every connection has its own filter, you can cleanly route different event types to different destinations.

Example: one Stripe source, three connections — charge.* events go to your billing service, customer.* events go to your CRM, and everything else goes to an S3 archive.

Content-Based Filters

Connections support filters with 9 operators that evaluate against the event's method, headers, content type, source IP, or payload:

  • eq / neq — exact match / inverse match
  • contains — substring match (strings only)
  • gt / gte / lt / lte — numeric comparisons
  • exists — field is present (true) or absent (false)
  • in — value is within an array of allowed values

Filters use dot-notation paths like payload.event.type to reach nested fields. Multiple filters are AND-combined — all must match for the event to pass. See Filters & Transforms for the complete operator reference.

JSONata Transforms

Connections can reshape the event payload before delivery using a JSONata expression. Use it to flatten nested structures, strip sensitive fields, compute derived values, or convert between formats. Transforms run after filters, before the event is handed to the destination's DO.

jsonata
{ "event_type": body.type, "customer_id": body.data.customer.id, "amount_usd": body.data.amount / 100 }

JSONata runs in a sandboxed interpreter — no eval(), no filesystem, no network. It's safe to let users author their own transforms.

Processing Order

When an event arrives at a source:

  1. All connections for the source are loaded from D1.
  2. Content-based filters are evaluated for each connection.
  3. Matching connections apply their JSONata transforms.
  4. Each transformed payload is dispatched to the destination's DeliveryScheduler DO via waitUntil().

Connections are evaluated in parallel — there's no ordering guarantee between them. If you need strict ordering, put the ordering logic on the receiving side.

Next Steps

Filters & Transforms

All 9 operators plus JSONata transform patterns.

Learn More
Connections API

Create and manage connections via the API.

Learn More
Sources

Where events come from.

Learn More
Destinations

Where events go.

Learn More
Ask a question... ⌘I