Targets

Kafka

Publish captured changes to Apache Kafka topics as keyed JSON events, with TLS and SASL authentication.

A Kafka target publishes every captured change as a JSON message, keyed by the row's primary key, to one topic per table or to one shared topic. Use it when downstream consumers read a change stream rather than a replica table.

Requirements

RequirementDetails
BrokersReachable from the agent that applies the pipeline, at the addresses you list in Bootstrap servers
TopicsMust exist, or the brokers must create topics automatically. SQL Flow doesn't create topics.
Primary keysEvery captured table needs a primary key on the source. A table without one stops the pipeline at startup.
Message sizeEach event must fit in 1,000,000 bytes. The topics must accept messages of that size, which Kafka's default limit does.
SourcesEvery source and capture mode.

Topic settings

SQL Flow works with any partition count and replication factor. When you create the topics:

  • Partitions. Every event of a row carries the same key, so each row's events go to one partition and stay in order. Order across rows isn't kept. Adding partitions to a topic later moves keys to other partitions, so a row's newer events can land on a different partition than its older ones.
  • Compaction. With cleanup.policy=compact, Kafka keeps the latest event per row. SQL Flow writes no tombstones: a deleted row's last event is its DELETE event, and compaction keeps it.
  • Durability. SQL Flow waits for every in-sync replica to acknowledge each message, so a replication factor of 3 with min.insync.replicas=2 keeps an acknowledged event through the loss of one broker.

Permissions

With SASL, the user in SASL username needs these ACLs. SQL Flow only produces messages, so it needs no permissions on consumer groups or transactional IDs.

ResourceOperationsWhy
Each topic the pipeline publishes to: the topic in Fixed topic, or every topic that starts with Topic prefix (a prefixed ACL covers them)Write, DescribeProduce the events and read the topic's metadata
The cluster, on brokers older than Kafka 2.8 onlyIdempotentWriteSQL Flow's producer is always idempotent; newer brokers accept Write on a topic instead

What SQL Flow creates on the target

SQL Flow creates no topics and no other objects. It produces messages to existing topics.

Topic names

Topic routingTopic for a table
A topic per table (default)Topic prefix followed by the source table name as you selected it, for example cdc-dbo.Orders for dbo.Orders with the prefix cdc-. With no prefix, the topic is the table name.
One topic for every tableThe topic in Fixed topic

The wizard shows the first topic names under the form, so you can check them before you continue.

Messages

Each message has:

  • Key: a compact JSON object of the row's primary-key columns, for example {"order_id":42}. With One topic for every table, the key also carries the table, for example {"__table":"dbo.Orders","order_id":42}. Every event for one row, including its snapshot, has the same key, so log compaction and keyed upserts work.
  • Value: a JSON envelope.
  • Headers: cdc-table (the source table), cdc-operation (the operation) and content-type (application/json).
{
  "operation": "UPDATE",
  "table": "dbo.Orders",
  "timestamp": "2026-10-15T08:30:00+00:00",
  "data": { "order_id": 42, "status": "shipped" },
  "oldData": { "order_id": 42, "status": "new" }
}
FieldContents
operationINSERT, UPDATE, DELETE, or READ for a row from the initial snapshot
tableThe source table name
timestampThe change's timestamp, in ISO 8601. Snapshot rows of one table share the time that table's snapshot started.
dataThe row after the change
oldDataThe row before the change, present when the source supplies a before-image. How many columns it holds depends on the source; for PostgreSQL, see REPLICA IDENTITY.

Binary values are base64 strings, dates and times are ISO 8601 strings, and numbers that don't fit a JSON number exactly, such as very wide decimals, are strings. A column whose value the source didn't capture is left out of the event rather than sent as null.

Delete events

Where a DELETE event carries the deleted row depends on the source. Read oldData when it is present, and data otherwise.

Source and capture modedataoldData
PostgreSQL, REPLICA IDENTITY default or USING INDEX{}The key columns of the deleted row
PostgreSQL, REPLICA IDENTITY FULL{}The whole deleted row
MySQLThe whole deleted rowThe same row
SQL Server DirectLog and ReconstructionThe whole deleted rowThe same row
SQL Server PollingThe whole deleted rowNot present
SQL Server and Azure SQL Native CDCThe captured columns of the deleted rowThe same values
Oracle DirectLogThe whole deleted rowThe same row
Oracle LogMinerThe columns LogMiner records for the deleteNot present
Sybase ASEThe whole deleted rowThe same row

Large values stored outside the row can be missing from a delete event: off-row large values from SQL Server DirectLog and Reconstruction, out-of-row LOBs that are no longer in the Oracle DirectLog redo window, and LOB columns under Oracle LogMiner.

Delivery

  • Each row's events arrive in order, and a broker retry never reorders or duplicates messages within a partition.
  • Delivery is at least once. After a crash or a lost acknowledgement, SQL Flow publishes the unacknowledged changes again, with the same key and value. Consumers should upsert by key or ignore repeats.

Options

FieldOption keyValuesDefault
Bootstrap serversbootstrapComma-separated host:port list, for example broker-1:9092,broker-2:9092Required
Topic routingNot storedA topic per table, One topic for every tableA topic per table
Topic prefixtopicPrefixAny text; shown with A topic per tableNone
Fixed topictopicA topic name; shown with One topic for every tableRequired with that routing
Initial snapshotsnapshotModeSnapshot existing rows, then stream (default) (initial), Stream changes only (never)initial
Security protocolsecurityProtocolPlaintext (plaintext), TLS (ssl), SASL over plaintext (sasl_plaintext), SASL over TLS (sasl_ssl)plaintext
SASL mechanismsaslMechanismPLAIN, SCRAM-SHA-256, SCRAM-SHA-512; shown with a SASL protocolRequired with SASL
SASL usernamesaslUsernameThe SASL user; shown with a SASL protocolRequired with SASL
PasswordThe connection's password or secret referenceThe SASL password; shown with a SASL protocolRequired with SASL
Broker CA certificate (PEM)sslCaPemThe CA that signed the brokers' certificates; shown with a TLS protocolThe agent host's trust store
None (CLI only)sslEndpointIdentificationhttps (check the broker's host name), nonehttps
  • Initial snapshot. With Stream changes only, no existing row is published; consumers see changes only.
  • Security. With Plaintext, the agent connects without authentication or encryption. With TLS, it verifies the brokers' certificates and connects without a SASL credential. GSSAPI (Kerberos), OAUTHBEARER and client certificates aren't supported.
  • Host name check. Set sslEndpointIdentification with the sqlflow CLI, for example --opt sslEndpointIdentification=none on sqlflow connection add. Turning it off accepts any certificate the CA signed, whatever host it names.

Test connection proves that the brokers are reachable and that the credential and certificate work. It doesn't produce a message, so it passes before any topic exists or any topic ACL is granted.

Limitations

  • Every captured table needs a primary key on the source. Otherwise the pipeline stops at startup with This target derives row identity from the source key; startup is refused rather than falling back to a table-name or conventional-id key.
  • An UPDATE that changes a primary-key value stops the pipeline: one event can't move a row from one key to another.
  • A TRUNCATE captured from the source stops the pipeline.
  • Reload isn't available: Pipeline <id>: Reload isn't available for kafka targets, because published events and files can't be withdrawn. Create a new pipeline to publish a fresh snapshot.
  • A message larger than 1,000,000 bytes stops the pipeline with Kafka event for '<table>' is larger than the 1,000,000-byte message limit. SQL Flow doesn't split or truncate events; reduce the row's size or leave the column out with output columns., or Serialized Kafka event is approximately <n> bytes, over the 1,000,000-byte message limit for topic '<topic>'. The limit can't be raised. To leave a large column out, see in-flight processing.
  • Only JSON is produced. There is no Avro, Protobuf or schema registry support, and no dead-letter topic: an event that can't be published stops the pipeline.
  • A pipeline stopped during the initial snapshot publishes the snapshot of every table again from the start when it restarts, so a topic that isn't compacted can hold duplicate snapshot rows.

See also

If this was useful,
our newsletter will be too.

Get monthly insights on data engineering, AI, and building critical infrastructure - direct from the Spectral Core team and CEO Damir Bulic.