Overview
Camunda Zeebe Source Connector publishes Zeebe Jobs from workflows to Kafka, connecting message-sending steps in a process to event processing, business notifications, and data integration pipelines. It actively claims jobs by Job type, uses a job’s custom header to specify the destination Topic, and uses the Job key and the activated job’s JSON content as the message key and value. The Connector also acts as a Zeebe worker and sends job completion commands so that the process can continue. It is not a passive subscriber to process logs and does not export all process events or historical records. Each valid job produces one record for a single Topic. When other workers use the same Job type, the workers compete to claim jobs rather than each receiving a broadcast copy.Prerequisites
- The Zeebe process must contain an activatable service task whose Job type matches the Connector’s
job.types. The task’s custom header must provide a single valid Kafka Topic name, and the Connector must be allowed to complete the task and advance the process. - The gRPC gateway for Self-Managed Zeebe typically uses port
26500; connections must match the gateway’s TLS and authentication settings. Camunda SaaS requires a cluster ID, region, and client credentials with the appropriate access permissions.
License
Uses Apache License 2.0.Quick Start
Prepare a Connect Cluster, Kafka, and a local Self-Managed Zeebe 8.4 deployment, and verify access permissions and network connectivity. For Connector creation and management, see Manage Connectors. This example uses a local Zeebe gateway with TLS and authentication disabled. The gateway and Connect Worker share the same network namespace, so the gateway is accessible atlocalhost:26500.
Deploy a process in Zeebe that contains a message-sending service task: set its Job type to kafka and its custom header key to kafka-topic, with the value workflow-events. Prepare this Kafka Topic in advance and start a process instance so that it reaches the service task. Enter the following Connector configuration:
localhost:26500, the default Job type is kafka, and the default routing header is kafka-topic, so the example does not repeat these values. If the Worker runs in a separate container or on a remote host, set zeebe.client.gateway.address to a gateway address that the Worker can actually access. Inside a container, localhost does not refer to the host or another container. Plaintext connections are appropriate only for the local environment described here, where TLS is explicitly disabled.
After the configuration takes effect, check for messages in workflow-events and verify in Zeebe that the task completes and the process continues. The message key is a 64-bit Job key encoded by LongConverter, not a number represented as text. The message value is the activated Job JSON encoded by StringConverter, not just the process variables. Consumers should parse the outer job content before reading variables and should not assume an unconfirmed representation of the variables field. Check Kafka publication and Zeebe job completion separately: completion commands are sent asynchronously, so successful Kafka writes alone do not establish that the process has advanced.
Configuration
Connector and Output Encoding
connector.class
Selects the Zeebe Source Connector implementation.
- Type:
string - Default: No ConfigDef default
- Importance: High
- Required: Yes
- Valid Values / Notes: Use
io.zeebe.kafka.connect.ZeebeSourceConnectorand ensure that the class can be loaded.
tasks.max
Sets the maximum number of Tasks that Kafka Connect can create.
- Type:
int - Default:
1 - Importance: High
- Valid Values / Notes: Must be at least
1. The Connector assigns types from thejob.typeslist; a single distinct type is not automatically split across multiple Tasks. More Tasks than entries in the type list do not provide useful parallelism. Do not use duplicate types as shards.
key.converter
Overrides the Worker’s message key converter.
- Type:
class - Default:
null - Importance: Low
- Valid Values / Notes: Inherits the Worker configuration when unset. The key’s Connect type is
INT64, and its content is the Zeebe Job key. The Quick Start explicitly usesorg.apache.kafka.connect.converters.LongConverter; this is not the plugin default.
value.converter
Overrides the Worker’s message value converter.
- Type:
class - Default:
null - Importance: Low
- Valid Values / Notes: Inherits the Worker configuration when unset. The value’s Connect type is
STRING, and its content is the activated Job’s JSON text.org.apache.kafka.connect.storage.StringConvertercan encode this text directly. JsonConverter processes a string value; it does not automatically turn it into a structured Connect object.
Self-Managed Connections and Requests
zeebe.client.gateway.address
Specifies the Zeebe gateway address for a direct connection.
- Type:
string - Default:
localhost:26500 - Importance: High
- Valid Values / Notes: Use the gateway’s host and port. Takes effect only when
zeebe.client.cloud.clusterIdis unset; cloud connection mode does not use this setting.
zeebe.client.requestTimeout
Sets the direct client’s default request timeout and the upper bound for Source polling backoff, in milliseconds.
- Type:
long - Default:
1000 - Importance: Low
- Valid Values / Notes: ConfigDef declares no range validation; use a usable, nonnegative duration. Activation requests override the client’s default request timeout with the current backoff duration, so this setting is not a fixed timeout for every activation request. Cloud mode does not apply it as the client’s default request timeout, but Source backoff still reads it.
zeebe.client.security.plaintext
Controls whether a direct connection disables transport-layer TLS.
- Type:
boolean - Default:
false - Importance: Low
- Valid Values / Notes: Set to
trueonly when explicitly using a plaintext gateway. Cloud mode ignores this setting. Do not disable secure connections to bypass TLS configuration problems.
Cloud Cluster Selection
zeebe.client.cloud.clusterId
Selects Camunda SaaS connection mode and the cluster.
- Type:
string - Default:
null - Importance: Low
- Valid Values / Notes: Any non-
nullvalue selects cloud mode, including an empty string. For Self-Managed deployments, remove this setting rather than supplying an empty string. Cloud mode requires the corresponding client credentials. The Connector does not check credential completeness itself and does not use the direct gateway address, plaintext switch, or OAuth audience settings.
zeebe.client.cloud.region
Specifies the cloud cluster region.
- Type:
string - Default:
null - Importance: Low
- Valid Values / Notes: Passed to the client only in cloud mode and when non-
null. It should match the cluster’s actual region. When unset, the SDK handles it; this does not mean that the Connector provides a fixed default region.
Authentication
zeebe.client.cloud.clientId
Specifies the OAuth client ID.
- Type:
string - Default:
null - Importance: Low
- Valid Values / Notes: Cloud mode uses this ID. In direct connection mode, a non-
nullID enables the OAuth credentials provider, which uses the secret and audience. The Connector does not validate credential pairing itself; prepare credentials according to the gateway’s authentication requirements.
zeebe.client.cloud.clientSecret
Specifies the OAuth client secret.
- Type:
string - Default:
null - Importance: Low
- Valid Values / Notes: Cloud mode uses this value; direct connections use it only when a client ID is set. It is registered as
STRING, notPASSWORD, so do not assume that configuration displays automatically redact it. Supply it through the platform’s secret management mechanism, and do not expose it in logs or shared configurations. The property name isclientSecret; do not replace it with another SDK property name.
zeebe.client.cloud.token.audience
Specifies the token audience for direct-connection OAuth credentials.
- Type:
string - Default:
null - Importance: Low
- Valid Values / Notes: Used only when the cloud cluster ID is unset and the client ID is set. Enter the audience required by the authentication system. Cloud mode ignores this setting, and
nulldoes not represent a fixed audience string.
zeebe.client.cloud.authorization.server.url
Specifies an authorization server URL, but this version does not use the setting.
- Type:
string - Default:
null - Importance: Low
- Valid Values / Notes: In Connector 0.51.0, this setting is not applied when building the client, so changing it cannot configure the token retrieval endpoint. Do not treat it as a usable setting for a custom OAuth authorization URL.
Job Selection and Routing
job.types
Selects the Zeebe Job types to activate.
- Type:
list - Default:
kafka - Importance: High
- Valid Values / Notes: A comma-separated list of types that must not be empty after parsing. Matches the Job types of service tasks; it does not support regular expressions and is not a process event type filter. The list is not automatically deduplicated; use distinct types.
job.header.topics
Specifies the Zeebe custom header key containing the destination Kafka Topic name.
- Type:
string - Default:
kafka-topic - Importance: High
- Valid Values / Notes: The configuration value is the header key, not a Topic name. Each Job must provide a nonempty, valid, single Topic name under this key. The entire header value is used directly as the destination Topic; it is not split on commas and does not perform multi-Topic fan-out. A nonempty check alone does not establish that a Kafka name is valid.
job.variables
Selects the process variables to fetch when activating jobs.
- Type:
list - Default: Empty list
- Importance: Low
- Valid Values / Notes: Use comma-separated variable names; an empty list fetches all variables. This setting only narrows the variables fetched. It does not filter Jobs or remove the outer job metadata and custom headers.
Job Activation and Timeouts
zeebe.client.worker.name
Specifies the Zeebe worker name used when claiming jobs.
- Type:
string - Default:
kafka-connector - Importance: Low
- Valid Values / Notes: Passed unchanged to the job activation command. It is not the Kafka Connect Worker name and does not establish an exclusive lock or job sharding.
zeebe.client.worker.maxJobsActive
Sets the target capacity for activated and in-flight jobs per Task, per Job type.
- Type:
int - Default:
100 - Importance: Medium
- Valid Values / Notes: ConfigDef declares no range validation; use a positive integer. Zero or negative values provide no activation capacity. This is not a strict in-flight limit for the entire Connector or a global batch size for one poll. When adjusting it, observe actual operation alongside write latency, backlog, and Worker resources.
zeebe.client.job.timeout
Sets the lock duration after Job activation, in milliseconds.
- Type:
long - Default:
5000 - Importance: Medium
- Valid Values / Notes: ConfigDef declares no range validation; use a positive duration that covers actual Kafka write and Zeebe completion latency. Unfinished jobs can be activated again after the timeout, and the Connector does not automatically renew the lock. This is neither the activation RPC request timeout nor the Connect offset commit timeout.
Best Practices
Define Message Content During Initial Integration
Business Scenario: The process already has a message-sending step, and downstream consumers need to be connected. Before connecting them, define the variables and message encoding they need instead of exposing all process variables by default. Configuration Example: Add the following setting to the Quick Start configuration.orderId and status are variable names in the example process; replace them with variables that consumers actually need and that the process already provides.
Allow Time for Failure Recovery During Normal Operation
Business Scenario: The Connector is running continuously, but slower Kafka writes, brief network interruptions, or Task restarts may cause jobs to be claimed again. Normal processing needs enough time, and consumers need to recognize duplicate jobs. Configuration Example: Add the following setting to the Quick Start configuration.30000 milliseconds is an example adjustment; determine the value from actual write and completion latency.
Increase Parallel Processing Across Existing Job Types
Business Scenario: The integration expands from one job type to multiple existing message-sending job types, and sequential activation of different types by a single Task has begun to affect processing latency. Assign the different types to different Tasks to avoid adding idle Tasks that cannot handle those jobs. Configuration Example: Add the following settings to the Quick Start configuration. The example process already uses the Job typesorder-events and shipment-events; jobs of both types must have valid Topic headers.
kafka type; only the listed types are claimed. Before expanding, confirm that all target types are in the list and observe Task assignment, throughput, and latency. Reconfiguration may regroup types. Do not increase the Task count beyond the number of distinct types solely to meet throughput needs; one busy type is not automatically split across multiple Tasks. Do not duplicate list entries or redesign business job types just to increase parallelism. More Tasks may increase the total number of activated jobs, so also monitor resources and job backlog. Global ordering across types, Tasks, or Kafka partitions is not guaranteed.
Monitoring
What to Monitor
Monitor Kafka Connect Connector / Task status, throughput and end-to-end latency, offset commit duration and failures, errors and retries, and Worker JVM heap memory, GC, and thread signals. A Task in RUNNING state does not necessarily mean it has successfully claimed or published jobs; assess actual messages and logs as well. Monitor DLQ activity only when the deployment enables the corresponding error handling, and do not treat DLQ activity as proof of Zeebe job completion.Import the Grafana Dashboard
Download the shared Kafka Connect Grafana Dashboard, confirm that Kafka Connect metrics are collected into a compatible Prometheus data source and that collection labels match the cluster, Connector, and Task labels used by the dashboard, then import the JSON into Grafana and select the corresponding data source.Limitations
- The data input consists of activatable Jobs of the specified types. Exporting all process events, replaying historical records, or filtering jobs by process ID, element, tenant, or arbitrary conditions is not supported.
- Each Job routes to only one Topic; comma-separated strings in custom headers are not expanded into multiple destination Topics.
- The Connector does not automatically split a single distinct Job type across multiple Tasks. Increasing
tasks.maxdoes not directly improve parallelism for a single type. - Kafka writes and Zeebe job completion do not form a cross-system atomic transaction. Completion commands do not wait for asynchronous acknowledgment; the Connector provides neither end-to-end exactly-once nor unconditional at-least-once delivery guarantees.
- Connect offsets contain the Job key but are not used to locate or filter jobs at startup. Resetting offsets does not republish completed Jobs.
- The Connector does not automatically renew activation locks or guarantee that all asynchronous completion commands have been acknowledged when it stops.
zeebe.client.cloud.authorization.server.urlhas no effect in Connector 0.51.0 and cannot configure a custom token retrieval endpoint.
FAQ
Why Are There No Messages in the Topic When the Task Shows RUNNING?
Check whether the process has reached an activatable service task, whether its Job type matchesjob.types, and whether other workers are competing for the same type. Then check the gateway address, TLS and authentication modes, and activation error logs; persistent authorization errors may also appear as empty polls. Confirm that the header points to a single valid Topic, that the Topic exists and permits writes, and check for Converter and Kafka write errors. Running status alone does not establish successful connectivity or publication.
Why Does a Missing Topic Header Cause a Job Failure or an Incident?
When a job lacks the specified header or its value is empty, the Connector produces no output record. Instead, it asynchronously sends a job failure command that decreases the remaining retry count by one. If Zeebe accepts the failure command, jobs with retries remaining can be claimed again; exhausting the retries produces an incident. Check that the key specified byjob.header.topics matches the process definition and correct the Topic header in the process. Handle existing failed jobs through Zeebe incident and retry management. A nonempty but invalid Topic name may pass the local check and fail during Kafka writes. Check Kafka errors rather than expecting the missing-header handling path to address it.
Why Do Two Topic Names Not Produce Two Messages?
The header value is not split on commas; the entire value is treated as one Topic name. Change the header to a single valid Topic. If the business needs multiple destinations, design separate message-sending steps in the workflow or implement distribution downstream in Kafka rather than relying on this Connector’s header for fan-out.Why Does the Message Contain Job Metadata Instead of Just Variables?
The message value is the activated Job’s JSON, including the outer job content.job.variables only controls which variables are fetched; it does not strip the outer structure. Parse the message according to its actual encoding and extract the required variables. When using JsonConverter, distinguish its wrapping of the string from the Job JSON itself. To read JSON text directly, use StringConverter as in the Quick Start.
Why Does the Process Not Continue Even Though Kafka Has a Message?
Job completion commands are sent asynchronously, and the Connector neither waits for nor checks their asynchronous results. Successful Kafka writes do not prove that Zeebe has acknowledged completion. Check the job’s actual state in Zeebe, gateway connectivity and authentication, and whether the job has timed out and been reactivated. Restore connectivity and handle jobs that remain unfinished, reconciling published messages with process state according to business requirements. Do not reset Connect offsets as a process repair measure.Why Does the Same Job Key Reappear After a Restart, While Resetting Offsets Does Not Replay Jobs?
If a failure or lock timeout occurs after a Kafka write but before Zeebe completion acknowledgment, an unfinished job may be activated again with the same Job key. Consumers should implement idempotent handling using that key and adjust the Job lock duration according to actual latency. Connect offsets are not read as replayable cursors; completed Jobs are not reactivated by offset resets. To resend business messages, use business compensation or new process tasks.Why Does Changing the Authorization Server URL Not Change the Authentication Endpoint?
Although Connector 0.51.0 registerszeebe.client.cloud.authorization.server.url, it does not apply it to the client. Confirm whether cloud mode or direct connection mode is in use and check the applicable client ID, secret, and audience. Repeatedly changing this setting cannot switch the token endpoint. If the deployment requires a custom authorization endpoint, choose an integration that explicitly supports that authentication method, or confirm support in the target Connector before upgrading.