Inbound sources

Choose an inbound transport with your eyes open: what each one guarantees about ordering, acknowledgement, redelivery, and where a dedupe id comes from.

Duraton receives events two ways today: a webhook source that a sender posts to, and a Kafka source that the engine consumes from a broker. Configuring them looks the same. The transports underneath do not behave the same, and this page is where the differences are stated rather than implied away.

Every transport ships a capability descriptor. You can read it from the engine rather than from this page, which is the point - the table below is generated from the same closed sets the API serves:

curl -H "Authorization: Bearer $DURATON_API_KEY" "$DURATON_URL/ingress-kinds"
const kinds = await duraton.events.ingressKinds();

What each transport guarantees

Webhook sourceKafka source
Ordering (transport)noneper-partition
Acknowledgementsynchronous - the response status is the ackpositional - committing an offset acks everything before it
Who redeliversthe sender, on their own policythe broker, from its own retained state
Run ordering (Duraton)nonenone
Default dedupe idnone - every accepted request becomes an event unless the source names a dedupe keytopic:partition:offset
Dedupe id configurableyesyes

Ordering is two questions, not one

A broker's ordering is not an ordering your runs keep. Kafka guarantees the records in one partition arrive in order. Duraton does not preserve that past ingest: runs are admitted from a queue sorted on when they are due, with no creation-order tiebreak, and a concurrency key buys mutual exclusion rather than sequence.

That is why the descriptor carries two fields. ordering is what the transport promises on the way in; runOrdering is what survives, and it is none for every transport today. Reading the first without the second is the mistake this page exists to prevent - it is a true fact about your broker that reads as a promise about your workflows.

If your workload needs records for one key handled in order, ordering at the transport is not enough. Model it explicitly: one workflow that processes a batch in order, or a state machine keyed on the entity, rather than assuming per-partition delivery becomes per-partition execution.

Acknowledgement is what makes durability possible

The promise is that work triggered by a message actually finishes. That rests on being able to tell the transport a message was handled - and to not tell it when the message was not.

  • Synchronous (webhooks): the HTTP status is the acknowledgement. There is nothing to acknowledge later, so a sender that gives up is the end of it. That is why an inbound delivery is recorded and can be replayed manually.
  • Positional (Kafka): committing offset N acknowledges everything before it. The connector commits on acceptance rather than on completion, and holds the offset when Duraton will not take a record.

A transport that acknowledges nothing cannot carry the promise honestly. Redis pub/sub and MQTT QoS 0 are fire-and-forget: nothing is retained, nothing is replayed, and a consumer that was not listening simply missed the message. Duraton does not offer them as sources rather than accepting them and quietly delivering a weaker guarantee under the same name.

Where a dedupe id comes from

A dedupe id is what makes a redelivery a no-op rather than a second run. There is no universal formula for it, and the descriptor says so per transport rather than pretending otherwise:

  • Kafka's topic:partition:offset is stable across redelivery, so it is the default.
  • A webhook has no equivalent, so there is no default: a source that wants dedupe names a key to read from the payload or a header.

Both are overridable with a template. The default is the transport's to declare, because it depends on what that transport actually keeps stable - and for some, nothing is. A RabbitMQ delivery tag, for instance, is scoped to a channel and is not stable across redelivery, so it could never play the role Kafka's offset triple plays.

Next

On this page