Skip to content

Kafka

A kafka binding is a typed connection to a Kafka topic — the durable, cross-instance sibling of an in-process topic. You produce with .send(v) from any handler; values cross the wire as JSON.

weld
type Order = { id: int, item: string }

kafka orders -> Order {
    brokers env("KAFKA_BROKERS")   # comma-separated host:port list
    topic   "orders"
}

route POST "/orders" (body o: Order) -> string {
    orders.send(o)                 # produce to Kafka
    respond "published"
}

Producing

name.send(v) JSON-encodes v (which must match the binding's message type) and produces one record to the topic. It speaks the Kafka wire protocol directly — no client library or sidecar — using a Produce request with a v2 record batch (CRC32C checked), so any Kafka-compatible broker (Apache Kafka, Redpanda) accepts it.

send is best-effort: broker/connection errors are logged, not thrown, so a Kafka blip never fails the request. For guaranteed delivery, produce from a worker that can retry.

Consuming

Consume a binding with for m in name inside a worker — the durable counterpart of consuming an in-process topic:

weld
worker {
    for o in orders {          # blocks for the next record; ends on shutdown
        ship(o)                # process it — write a DB row, call an upstream, …
    }
}

Each record's JSON is decoded into the binding's message type. Weld consumes with the message's committed group offset (or the earliest record for a new group), and commits progress as it goes — so a restart resumes where it left off (at-least-once). One worker per binding drains the topic; state touched in the loop is locked per message.

Configuration

FieldMeaning
brokerscomma-separated host:port bootstrap list (usually env(...))
topicthe Kafka topic name
groupconsumer group id for committed offsets; defaults to the binding name

Any of these can be an expression, so pull them from the environment per deploy.

Configuration

FieldMeaning
brokerscomma-separated host:port bootstrap list (usually env(...))
topicthe Kafka topic name
groupconsumer group id (for consuming; defaults to the binding name)

Any of these can be an expression, so pull them from the environment per deploy.

Scope

Weld speaks the Kafka wire protocol against the bootstrap broker — ideal for single-broker and dev/staging clusters (Apache Kafka, Redpanda). Producing sends to partition 0 with acks=1; consuming reads all partitions and commits offsets to the group. Still to come:

  • Multi-broker leader/coordinator routing (via Metadata/FindCoordinator) for large clusters.
  • Partitioning by key, producer batching/compression, and configurable acks.
  • Consumer groups with rebalancing (today one consumer instance owns the topic).