Kafka clients for Python, Go and .NET built on librdkafka

Teams writing Kafka producers and consumers outside Java need a client they can trust for delivery guarantees, security and upgrades. This page explains how librdkafka and the confluent-kafka libraries fit that need and what to verify before you commit.

On this page

Choosing a librdkafka-based Kafka client for Python, Go and .NET

Services written in Python, Go or .NET need to produce to and consume from a self-hosted Kafka cluster, and the first decision is which client library to use. Apache Kafka is licensed under Apache-2.0 and the project offers no paid edition, so choosing a client carries no licensing cost from the project itself. Client choice is also separate from broker choice: the same cluster serves Java, Python, Go and .NET applications, provided each client supports the protocol features your workloads depend on. librdkafka is a C client library that implements the Kafka protocol, and the confluent-kafka packages for Python, Go and .NET are built on it. Those packages give non-Java teams a producer and consumer API without running a JVM in those services.

A non-Java client is the right choice when the service already runs in Python, Go or .NET and adding a JVM would complicate deployment, monitoring and image size. The Java client is the reference implementation maintained alongside the broker, so it is the first place new Kafka features appear. The librdkafka-based libraries follow their own release cadence, which means a feature can exist in the Java client before it is available in your wrapper version. Kafka Streams is a Java library, so stream processing in these languages requires a different design, often a separate processing service or a framework with its own Kafka integration. Teams that need Kafka Streams semantics across several languages should plan for that split early.

Before you commit, pin the wrapper version and check which librdkafka version it bundles. Confirm that idempotent production and transactions work with your broker version in a test environment, and run a failure test that restarts a producer mid-transaction. Compare the authentication options you need, such as SASL mechanisms and TLS, with the Kafka security overview, then verify each one against the wrapper's documentation rather than assuming parity. Record the client and broker versions in your service inventory so that a broker upgrade triggers a compatibility check on every non-Java service.

Which client library fits which language and delivery need

This table compares the Java reference client with the librdkafka-based libraries for Python, Go and .NET. Use it to see where each library comes from and which features to verify before you choose. Treat each library's current release notes as the source of truth, because feature parity with the Java client is something to confirm, not assume.

LibraryMaintainer or source to verifyFeature coverage to confirmWhen it fits
Java client (reference)Apache Kafka project, in the apache/kafka repositoryIdempotence, transactions, admin API and newer protocol features, checked against the release notes for your broker versionJVM services, Kafka Streams applications and teams that need new client features first
librdkafka (C core)Confirm the maintainer and license in the librdkafka repositoryIdempotence, transactions and consumer group behavior in its release notes, since wrappers inherit themTeams building or embedding their own wrapper, or working in C and C++
confluent-kafka-pythonConfirm the maintainer and package source on the Python package indexProducer idempotence, transactions, offset commits and admin calls in the changelog for the version you pinPython data jobs and services where the wrapper's build needs fit your image pipeline
confluent-kafka-goConfirm the maintainer and module source in the Go module repositoryTransactions, rebalance callbacks and bundled librdkafka version, which determines feature supportGo services where a cgo build step is acceptable in your build and release process
confluent-kafka-dotnetConfirm the maintainer and NuGet package source in its repositoryTransactions, admin API and the bundled native librdkafka version for each target platformServices on .NET runtimes where you have confirmed supported operating systems and architectures
Broker version alignmentKafka upgrade notes and the Kafka downloads page for supported broker releasesClient version against each broker version in your fleet, including during rolling upgradesMixed client fleets, staged upgrades and environments where clients upgrade on a different schedule

Where non-Java clients differ from the Java client

Assessing feature parity starts with a side-by-side list: the features documented for the Apache Kafka Java client, mapped against what each non-Java library supports in the exact versions you plan to run. Treat the Java client as the reference, not the library's marketing page. Work through the consumer group protocol first, since rebalance behavior, static membership and cooperative assignment decide how your consumers behave during deploys and failures. Confirm each item against the library's own release notes and changelog, and record the version where support appeared. Admin API coverage is the second gap to check: list the topic, partition, configuration, ACL, quota and consumer group operations your platform team relies on, and verify each one is exposed by the library, not only by the broker.

Next, check interceptors and serializers. The Java client offers pluggable interceptors and serializer hooks that many teams use for tracing, header injection and schema registry integration. Non-Java libraries often expose different equivalents, or none, so any custom hook you rely on must be rebuilt in the application code or confirmed in the library. Also confirm which schema registry serializers the library supports for your format, since these are often maintained separately from the core client. Kafka Streams and Kafka Connect are Java-based and are not reproduced by these clients. If a Python, Go or .NET service needs stream processing or a managed connector, plan it as a separate Java component or a different pattern, and budget that work explicitly.

Finally, verify the list with a proof-of-concept against your broker version, not the latest client. Run the producer and consumer paths with idempotence and transactions enabled, force rebalances during load, kill a consumer mid-batch, and rotate TLS or SASL credentials while traffic flows. Exercise every admin call your automation makes, including failure responses. Record which behaviors differ from the Java client and decide whether each difference is acceptable, fixable in code, or a reason to standardize on Java for that service. Ask your library maintainers or vendor which broker versions they test against, and keep the proof-of-concept results with the version pins so the decision can be reviewed at upgrade time.

Idempotence and transactions in librdkafka clients

The librdkafka-based clients give Python, Go and .NET services the same delivery guarantees as the Java client, but only when producer and consumer settings are chosen deliberately. The cards below cover the decisions that determine whether a retry, a restart or a consumer rebalance can duplicate or drop records. Behavior should be tested with the exact library version you plan to run.

Idempotent producer defaults

The idempotent producer stops duplicates that retries would otherwise create within a partition. Confirm in the client configuration reference for your chosen library whether enable.idempotence is on by default in its release, and check that no other setting, such as a retry or acknowledgment override, silently disables it. Idempotence covers producer retries only. It does not make application-level resubmission safe, and it does not order records across partitions.

Transactional ID uniqueness

Each transactional producer needs a transactional.id that stays stable across restarts of the same logical instance and differs between concurrently running instances. Services that scale out by copying one configuration file often reuse the same ID, which causes fencing storms. Design the naming scheme with your deployment tool, for example by deriving the ID from a stable pod or task index, and document who owns it.

Read-committed consumers

A consumer that reads transactional topics must set isolation.level to read_committed to skip records from aborted transactions. The default of read_uncommitted returns those records, so a pipeline can appear to process data that was never committed. Test this with a deliberately aborted transaction in a non-production topic, and confirm that downstream teams know which consumers are configured for it.

Offsets committed inside transactions

For read-process-write flows, the consumed offsets should be sent inside the same transaction as the output records, so the two commit or abort together. Use the transactional offset commit call in your library rather than a separate commit after produce. Check that the consumer group metadata is passed correctly, since a mismatch breaks the guarantee without an obvious error.

Zombie producer fencing

When a new instance registers with the same transactional.id, the broker fences the older instance, which then fails its next transactional call. Your code must treat fencing as a signal to stop, not as a transient error to retry. Test a forced restart during an open transaction, and confirm that the fenced instance does not write to output topics after the replacement starts.

Limits with external systems

Kafka transactions cover writes to Kafka topics and offset commits only. A database update, an HTTP call or an email sent from a consumer sits outside the transaction, so a crash between the external effect and the commit can repeat it. Plan idempotent writes or deduplication keys in those systems, and verify the end-to-end behavior with failure injection before relying on it.

How to set up and verify a non-Java Kafka client

This sequence takes a Python, Go or .NET service from version checks against the broker to a tested producer and consumer that behave correctly under retries, ordering needs and broker failover. The result is a client configuration your team can reproduce and a test record it can keep.

  1. Confirm broker and client version compatibility

    The platform or integration lead records the Kafka version and the KRaft mode of the target cluster, then checks the client library's release notes for the broker versions it supports. Confirm which Kafka releases are supported on the downloads page and whether your cluster can take the upgrade path it needs. Done when the team has a written pair of broker version and client version, with the source of each compatibility statement attached to the change request.

  2. Choose the library and pin its version

    The engineering lead selects between the librdkafka-based libraries for Python, Go and .NET and confirms that each one exposes the producer, consumer and transaction features the service needs. Pin the exact library version in the lockfile or module file, and pin the librdkafka version it bundles, so that a routine dependency update cannot change delivery behavior. Done when a clean build on a fresh machine resolves to the same library and native library versions recorded in the review.

  3. Configure TLS and SASL authentication

    The platform engineer creates a client identity for the service and configures encrypted transport with the broker's CA certificate, using the security settings the library exposes for SSL and SASL. Choose SCRAM-SHA-256 or SCRAM-SHA-512, or OAUTHBEARER if your cluster has an OAuth identity provider configured, and confirm the mechanism is enabled on the listener you intend to use. Done when a connection test reports a successful handshake and a connection attempt with a wrong password fails with an authentication error, not a timeout.

  4. Set producer delivery settings

    The service owner sets the producer's acknowledgment, retry, idempotence and in-flight request settings, and documents the reason for each value. Confirm that idempotence is enabled and that no configuration in the service silently overrides it, because some combinations disable it. Use a transactional ID only if the service needs transactions. Done when the effective configuration is logged at startup and matches the reviewed values, and the team can show the logged output to an auditor or reviewer.

  5. Create a test topic matching production

    The platform team creates a test topic with the same partition count, replication factor, retention and key scheme as the production topic, and grants the service's principal only the ACLs production uses. Testing with an open or wider ACL set hides authorization failures that would appear after go-live. Done when a produce request succeeds with the service identity and a produce request from an identity without write permission is denied, both recorded in the test log.

  6. Run produce and consume tests

    The developer sends a known set of keyed messages and consumes them with a consumer group, checking that every record arrives with the expected key, headers and payload. Include records for each key so that per-key ordering can be verified against the partition layout. Done when the consumed count matches the produced count and the output shows the expected partition for each key.

  7. Verify duplicates, ordering and failover

    The team forces retries by briefly interrupting a broker or network path during a produce run, then checks the topic for duplicate records and for out-of-order records within each partition. Repeat the test with a leader change, so the client has to reconnect and resume, and compare the consumed output with the produced set. Done when the results match the delivery guarantees the reviewed configuration claims, and any gap is recorded with a decision to accept it or fix it before go-live.

  8. Record the verified configuration

    The engineering lead stores the pinned versions, the effective client configuration, the ACL definitions and the test results in the service repository and the change record. Confirm that the same test can be rerun after each library upgrade and after each broker upgrade. Done when a second engineer can rerun the test suite from the repository and get the same pass results.

Aligning client versions with Kafka 4.x brokers

Client upgrades belong in the same plan as broker upgrades, because a librdkafka-based client that falls out of step with the brokers is the change most likely to surprise a team mid-upgrade. The Kafka downloads page lists 4.3.1, 4.2.2 and 4.1.2 as the supported releases, and the time-based release plan says rolling upgrades are supported from each release in the past year, which is the last three releases, to the latest version. Your broker target should be chosen from that list, and the client libraries you run should be checked against that same target before the broker work is scheduled. Keep an inventory that maps each Python, Go and .NET service to its confluent-kafka or librdkafka version, its runtime and the broker release it was last tested against.

Do not assume that a client which connects to a given broker version has been validated against it. For each library, confirm with the maintainers which Kafka broker versions it has been tested against, and whether that list includes the release you plan to run. Check the release notes for the librdkafka version bundled in each wrapper, because the wrapper version and the underlying librdkafka version are not always the same. Where a broker feature such as idempotence or transactions is required, confirm that the client version you have pinned supports it against your target broker, not just the feature name in the documentation.

Plan a test window that runs the pinned client versions against a staging cluster already upgraded to the target broker release, with produce, consume, transactional and offset-commit paths exercised. Upgrade brokers first only if your client inventory shows the clients are already validated for the new broker. Otherwise, upgrade the clients in the same change window, and keep a documented rollback for both. The Kafka upgrade notes are the next read for broker-side changes that can affect client behavior.

Securing client connections to Kafka

Every Python, Go and .NET service that talks to your brokers is a client that must prove who it is, encrypt what it sends and stay inside its authorized topics. The four controls below connect transport, identity, authorization and credential handling, and each one has to be set and checked in every language runtime, not only in the broker configuration.

TLS between clients and brokers

Kafka encrypts traffic between clients, brokers and tools with SSL/TLS, but security is optional, so a cluster can run unsecured or mix secured and unsecured listeners. For librdkafka-based clients, set security.protocol to an SSL-based value on every client and confirm that no service falls back to a plaintext listener. Check that the CA bundle used by each runtime trusts your internal certificate authority and that hostname verification stays enabled.

SASL mechanism selection

Kafka documents five SASL mechanisms for clients: GSSAPI (Kerberos), PLAIN, SCRAM-SHA-256, SCRAM-SHA-512 and OAUTHBEARER. Choose one per listener based on your identity estate, for example Kerberos where directory integration already exists or OAUTHBEARER where tokens come from an identity provider. Avoid PLAIN unless TLS is enforced on the same listener, because it sends credentials in a reusable form.

Confirming library support for the mechanism

The broker mechanism is only useful if the client library implements it in your runtime. Before you commit, confirm with the confluent-kafka package maintainers and the librdkafka release notes that the Python, Go and .NET bindings support your chosen SASL mechanism, including OAUTHBEARER callbacks and Kerberos keytab handling. Test each language with a real broker login in a staging cluster, not only a configuration check.

ACLs in the KRaft metadata log

In KRaft clusters the StandardAuthorizer stores ACLs in the cluster metadata log. Resources without ACLs are restricted to super users unless allow.everyone.if.no.acl.found is set to true, so a new topic is closed by default. Grant each service account only the topics, consumer groups and operations it needs, and keep allow.everyone.if.no.acl.found disabled in production unless you have a documented reason to change it.

Credential and certificate handling per runtime

Client credentials and private keys must not appear in source code, container images or shared configuration files. Each runtime loads secrets differently: Python services often read environment variables or mounted files, Go binaries bake in configuration unless it is injected, and .NET services commonly use configuration providers. Ask your platform team which secret store delivers the SASL password, keytab or client key, how rotation reaches running processes, and how a revoked service account is blocked.

Questions teams ask before choosing non-Java Kafka clients

Are librdkafka-based clients production-ready for idempotence and transactions?

Confirm this for the exact client library and version you plan to run, because supported features are defined per release and per language binding, not by the library name alone. Idempotent producers and transactions must be tested against your own brokers, security settings and failure cases before you depend on them. Check the release notes for each feature and confirm that the features you need are listed as supported for your language. Build a test that stops producers mid-transaction, restarts brokers and verifies that consumers reading with read_committed see no duplicates or partial transactions. Treat a passing test as evidence for your configuration only, and keep the results so platform owners and auditors can see what was verified.

What drives the effort of a non-Java Kafka client rollout?

Effort depends less on the programming language than on how many applications, topics and security settings the rollout touches. The main drivers are:

  • The number of applications and languages that produce or consume, each with its own dependency, build and deployment path.
  • Security configuration, including TLS, the SASL mechanism (such as SCRAM-SHA-512 or OAUTHBEARER) and the ACLs each client identity needs.
  • Delivery semantics. At-least-once, idempotent and transactional processing each change how you design the code, test it and monitor it.
  • Schema and serialization choices, and whether existing Java services already share the same topics.
  • Operational ownership, meaning who patches client libraries, investigates offset problems and watches client metrics.

Ask any partner to break its quote into these items so you can see where the effort sits.

Can our team roll out Kafka clients without outside help?

Often yes, if your team already runs Kafka brokers and has engineers comfortable with the client library in your target language, but the answer depends on skills you can name. Your engineers need working knowledge of partitions, consumer groups and offsets, and enough time to build a test harness that proves delivery behavior. Outside help usually adds the most value on security integration, failure testing and the documentation that your compliance owners will ask for. DeployOpen plans, implements, hardens, documents and supports self-hosted platforms in your own infrastructure, and most engagements are fixed-scope with scope agreed in writing before work starts. A useful self-assessment is to name who will own client library upgrades after go-live and whether that person has already run a broker upgrade.

How long does a proof of concept for a non-Java Kafka client take?

No duration is given here because it depends on scope, so ask for the timeline in a written proposal rather than a generic figure. The main drivers are the number of topics and message formats to test, whether transactions are required, and how much of your security setup (TLS, SASL and ACLs) must be reproduced. A proof of concept that uses plaintext on a single broker finishes quickly but does not show whether the client works under your authentication model. Ask the proposal to list the test cases, the environment they run in and the result that counts as success. Teams that already have a non-production cluster matching their production security settings usually reduce this work.

What does a Kafka client rollout need from our team?

A rollout needs decisions and access from your side as well as the engineering work. Plan to provide:

  • A non-production Kafka cluster with security settings close to production, plus access to the topics the clients will use.
  • Named owners for topics, ACLs and client identities, so access requests have a decision-maker.
  • Sample payloads and schemas, and the rules for how producers should handle retries and duplicates.
  • A decision on delivery semantics for each workload, agreed with the teams that own the data.
  • Application engineers who can integrate the client into existing code and review the changes.

In return, a well-scoped engagement should leave your team with documentation, configuration and runbooks for the clients it delivers.

How do client upgrades relate to Kafka broker upgrades?

Client upgrades and broker upgrades are separate tracks that must be sequenced, not merged into one change. The Kafka time-based release plan states that rolling upgrades are supported from each release in the past year, the last three releases, to the latest version. The downloads page lists 4.3.1, 4.2.2 and 4.1.2 as the supported releases. Confirm the required order and compatibility for your versions in the Kafka upgrade notes, and check that your client library and language runtime support the broker version you run. Java clients and Kafka Streams applications need at least Java 11 since Kafka 4.0. Schedule client upgrades after each broker change is verified, and retest transactional behavior on every client version you move to.

Does the Apache Kafka project charge for a commercial edition?

No. Apache Kafka is released under the Apache License 2.0 (Apache-2.0), and the project itself offers no paid edition. The cost of a self-hosted rollout comes from the infrastructure you run, the staff time your team spends, and any partner work you scope. Some costs are one-time, such as design, build and testing, while infrastructure and maintenance recur. Client libraries carry their own licenses, so confirm the license of each library in its repository before you standardize on it. The Kafka downloads page lists the supported releases and archived versions.

How DeployOpen scopes and delivers Kafka client work

DeployOpen plans, builds, tests and hands over Kafka clients for Python, Go and .NET built on librdkafka inside your own infrastructure. Each engagement starts from a written scope that fixes what the clients must do, which brokers and versions they target, and how the work is verified before handover.

How we scope

  • Inventory the producers, consumers and transactional flows each language service needs before choosing a client library.
  • Record the target Kafka version, cluster security settings and whether idempotence or transactions are required.
  • Agree deliverables, testing evidence and timelines in writing, since most engagements are fixed-scope.

How we build

  • Pin confluent-kafka and librdkafka versions against the broker release line your cluster runs.
  • Configure idempotent producers, offset commits and retry behavior explicitly rather than relying on defaults.
  • Test failover, rebalancing and TLS or SASL authentication against a staging cluster that mirrors production.

How we hand over

  • Deliver service code, configuration templates and a dependency map showing library and broker version alignment.
  • Document runbooks for consumer lag, client upgrades and certificate or credential rotation.
  • Walk your platform and application teams through the test results and the open items that remain.

How we support

  • Offer ongoing support, client upgrades and continuous testing as a retainer after handover.
  • Re-run compatibility checks when the broker, librdkafka or client library versions change.
  • Ask your team to confirm the support scope and response expectations in the written agreement before work starts.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.