Skip to main content

Configure event sources: Kafka inbound consume

An event source is the inbound mirror of an event sink: the sink streams the platform’s own event taxonomy out to your Kafka topic or HTTP collector, and the source consumes your own Kafka topic into Orbit. If you run Kafka as your event system of record, an inbound source lets Orbit subscribe to your domain events — orders, payments, fraud signals, CRM updates — and ingest them through the same filter and envelope semantics the sinks publish with.

What the dashboard page configures

Open Developer → Event Sources in the dashboard. The page ships one source kind today, kafka:
  • Enabled toggle — when off, configuration is saved but nothing is consumed.
  • Topic — the Kafka topic to consume from. 1–249 chars, [A-Za-z0-9._-], never . or ...
  • Consumer group — Kafka’s group.id for this subscription. 1–255 chars, [A-Za-z0-9._-].
  • Type path (optional) — dot-path into each decoded message that carries the event type. Defaults to type; set meta.event if your envelope nests it.
  • Bootstrap brokers — one host:port per line (no scheme, no path), up to 16.
  • SASL mechanism + usernameplain, scram-sha-256, or scram-sha-512. Skip SASL entirely if your brokers are not SASL-protected.
  • Event filter (optional) — one pattern per line: an exact type (order.created), a prefix glob (order.*), or * / blank to ingest everything. The filter vocabulary is shared verbatim with event sinks, so inbound and outbound subscription semantics never drift.
  • Credentials — the SASL password. Encrypted at rest, write-only: a read surfaces only a credentials_configured presence flag, so the password input always starts blank and is sent only when you type a new value. You can also permanently remove the stored secret with confirmation.

API backing

Everything the page does is available under /api/v1/developer/event-sources/:kind where :kind is currently kafka only: A PATCH example:
The source.kind discriminator must equal the path segment — a PATCH /…​/kafka with source.kind of anything else returns 400. Broker entries that carry a scheme or path (https://…​:9092) are rejected the same way.

Test consume batch — dry-run walkthrough

Before any transport runs, you can validate your topic, type path, and filter against real sample messages. In the dashboard’s Test consume batch panel, paste one raw JSON message per line:
Or call the endpoint directly:
The response assigns every message exactly one terminal disposition:
Read the dispositions as:
  • landable — decoded, typed, and subscribed; the envelope carries the resolved event type plus the verbatim decoded data.
  • duplicate — a redelivery of a coordinate (topic, partition, offset) already seen in this batch; skipped so you never double-ingest.
  • filtered — well-formed but the resolved type is not in your filter; skipped deliberately.
  • dead_letter — undecodable (invalid_json), not a JSON object (not_an_object), or missing the event type at the configured path (missing_type). Routed aside with structured errors so a poison message never blocks the partition.
commit_offsets reports the highest safe-to-commit offset per partition — every message at or below it reached a terminal disposition, so advancing the offset never drops nor re-skips a record. persisted: false on the read is deliberate: the dry run never writes anything.

Failure notes

  • Credentials are encrypted at rest and never returned by any read — a GET surfaces only credentials_configured. Rotating means saving a new value; removing means an explicit empty-string clear.
  • The dry run is honest about its limits — it does not persist envelopes and does not start a managed consumer. The long-running broker consumption transport is a tracked follow-up; what ships today is the config, validation, and the deterministic consume engine that transport will call per poll.
  • Feature-flagged transport — the consume engine is inert until the transport flag is enabled by an operator, so flipping enabled: true on the config alone cannot start broker consumption.
  • Poison messages dead-letter rather than stall a partition, and commit_offsets still advances past them.

When inbound events are useful

Use an event source when Kafka is your system of record and Orbit should mirror a baseline stream of your domain events — order creation driving a follow-up campaign, a payment-completed signal closing out a billing interaction, CRM updates refreshing contact profiles. The inbound path shares the subscription-filter model with sinks, so choosing what to ingest is the same decision, inverted.

Next steps