Open-source project
aio-libs/aiokafka avatar
aio-libs/aiokafka

aiokafka compiles Cython if it can and falls back to Python if it cannot

asyncio client for kafka

1,403 stars271 forksPythonApache-2.0

At a glance

What is it?
The asyncio Kafka client is mostly a pure-Python project with optional Cython extensions, which is the design decision that makes it installable on a laptop and fast in production. The rest is worth knowing: a 3.11 floor, compression behind extras, a transactional example, and a test suite that needs Docker and a Java keytool.
Who is it for?
Adopt aiokafka if you are running an asyncio service in Python and need Kafka without a blocking client, because the producer and consumer examples are short and the group coordination is handled for you, and if you keep Python 3.11 or newer, which the project requires. Do not adopt it if your service is synchronous, since wrapping a blocking client in an executor is a smaller change than migrating the service, and note that the project classifies itself as beta status.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 20 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The producer pattern is start, send, stop

The readme's producer example is the shape almost all code will follow, and it is worth reading for the comments as much as the code.

python
from aiokafka import AIOKafkaProducer
import asyncio

async def send_one():
    producer = AIOKafkaProducer(bootstrap_servers='localhost:9092')
    await producer.start()
    try:
        await producer.send_and_wait("my_topic", b"Super message")
    finally:
        await producer.stop()

asyncio.run(send_one())

A producer is constructed with bootstrap servers, then started, which the comment explains fetches the cluster layout and the initial topic and partition leadership information. Messages are sent with a send-and-wait call, which returns once the broker has acknowledged, and then a stop in a finally block, whose comment says it waits for all pending messages to be delivered or expire. Three things follow. First, start is not optional and not free: it is a round trip to the cluster, so a producer created per message throws that cost away. Second, the finally block is the difference between a clean shutdown and a half-flushed batch, and a program that exits without stopping the producer can lose messages that were accepted into the buffer. Third, the wording of that stop comment is a warning about timeouts: pending messages can expire rather than be delivered, so a shutdown path that needs certainty has to check what the send call returned. The send-and-wait form is the safe default for a system that must not drop messages, and the alternative fire-and-send form, which the library also offers, is for throughput where loss is acceptable and back-pressure is not something you want to inherit.

The consumer gets a group, and the group needs a broker

The consumer example constructs a consumer with a topic list, bootstrap servers, and a group identifier, then starts it, which the comment says joins the group, and iterates the consumer asynchronously. The readme is explicit that the consumer interacts with the assigned group coordinator node so that multiple consumers can load balance consumption of topics, and that this requires a broker of version 1.0 or later. That is an important line for anyone running an old cluster, because load balancing across consumers is a broker feature and an old broker will not provide it regardless of what the client does. The iteration yields a message with topic, partition, offset, key, value and timestamp, which is the whole of what you need to log or route. The stop call in the finally block has a comment saying it will leave the consumer group and perform autocommit if enabled, which points at a real operational decision: autocommit means offsets are committed as the library sees fit rather than when your processing finishes, and for anything where processing must succeed before the message is considered handled you want to commit manually after the work, not leave it to autocommit. The readme does not spell that out, so treat it as a question to answer in your own integration. The examples directory does have a local state consumer, which is the pattern for restarting a consumer where it left off.

Cython extensions are optional, and the fallback is silent

The build is where this project is unusual, and it is unusual in a good way. The build system requires setuptools and Cython, and the setup file declares four extension modules: a legacy record implementation, a default record implementation, an in-memory record implementation, and a shared utility module. The default record extension also compiles a C source file for a CRC32C implementation, and the extensions are linked against the platform's compression library on non-Windows systems, with the Windows build linking a different system library instead. Every one of those extensions is declared optional, and the build command is a custom subclass whose docstring says it allows installation to fall back to the pure-Python implementation. That is the design: a fast path when a compiler exists, a working install when it does not. The consequence to be aware of is that a failed compilation produces a successful install on the slow path, with nothing in the output to distinguish the two except the build log. On a platform with no toolchain, in a slim container image, or behind a wheel-only index, you may be running pure Python and not know it. If throughput matters to you, check that the extensions actually built, and remember that the performance-sensitive paths are the record handling code, which is exactly what the Cython modules replace.

Compression, transactions and metrics are the extras you will argue about

The optional dependencies tell you what the project considers optional in a Kafka client, and the list is short enough to read as a feature matrix. There are extras for snappy, lz4, zstd and GSSAPI for Kerberos, plus an all extra that installs the compression library and the GSSAPI package together. The lz4 extra carries a comment saying a specific library version adds support for independent-block mode, which is a detail about the codec's framing rather than about installation, and it tells you the project is keeping pace with the compression libraries. Kafka brokers have advertised several compression codecs and they are not interchangeable, so which extras you install determines which codecs you can send, and a mismatch between producer and broker capability shows up as a runtime error rather than a startup error. The examples directory is where the harder features are visible: a transactional producer, an idempotent producer, a batch producer, a producer and consumer pair over SSL, and a Prometheus metrics example. The presence of idempotent and transactional examples side by side is the useful signal, since idempotent production and transactions are different guarantees and a system that needs one is not automatically getting the other.

The test suite is a Kafka broker in a container, plus a keytool

Contributing is where the readme gets honest about cost. Running the tests requires Docker, and the instructions name a default Kafka version that can be overridden with a make variable along with a Scala version, which selects the container image the suite runs against. That means the test suite is an integration suite against a real broker, not a suite of mocks, and it is why the makefile's test targets all pass a docker image argument. The setup step installs Kerberos development packages on a Debian-family system before installing the development requirements, and the readme adds two prerequisites that are easy to miss: the lz4 compression libraries for Python need the python development package or source headers on Linux, and a valid Java installation is required because some tests generate SSH keys with the keytool utility. The test invocation is pytest with a max-fail count, and the makefile offers a filtering flag, a no-pull flag to skip pulling a fresh image, and a verbose variant. Running the lint step pulls in a formatter, a linter, a type checker with automatic stub installation, and a workflow security scanner, and the test target depends on lint, so lint failures stop the tests. That is a strict gate for a project of this size, and it is a reason contributors should expect to install more than they expected.

Maintenance, packaging, and the 3.11 floor

The project is being actively worked on and released. Recent versions include 0.14.0 on 2026-04-29, a 0.14.0 beta a few days earlier, and 0.13.0 in January 2026, so releases are frequent and pre-releases are published as separate artefacts, which means you can pin a beta if you want to test it. The last push to the master branch was on 2026-09-10, months after the newest release, so unreleased work is accumulating as usual. The project states that Python 3.11 or newer is required, the packaging metadata requires 3.11 or later, and the classifiers list 3.11 through 3.14, so there is no accommodation for older interpreters. The status classifier says beta, which is honest for a client at version 0.14. The licence is Apache-2.0, and the repository carries a changelog, a codecov configuration, a readthedocs configuration, a benchmark directory, a docker directory, a script for generating SSL certificates and a script for dumping a PEM file, all of which point to a project that tests against real infrastructure rather than a mock broker. The version is read from the package attribute rather than hardcoded, so there is a single place it is defined.

Editorial conclusion

Adopt aiokafka if you are running an asyncio service in Python and need Kafka without a blocking client, because the producer and consumer examples are short and the group coordination is handled for you, and if you keep Python 3.11 or newer, which the project requires. Do not adopt it if your service is synchronous, since wrapping a blocking client in an executor is a smaller change than migrating the service, and note that the project classifies itself as beta status. Four things to verify. That your interpreter is 3.11 or later, since the project states that requirement plainly and the packaging drops anything older. Which compression you need, because each codec is a separate extra and the lz4 extra needs a specific library version for independent-block mode. Whether your build environment has a compiler, because the Cython extensions are optional and the build falls back to pure Python when compilation fails, which means you can end up on the slow path without being told. And whether you need transactions, since the example set includes a transactional producer and a group coordinator that assumes a broker version of at least 1.0. The licence is Apache-2.0, version 0.14.0 was released on 2026-04-29, and the last push was on 2026-09-10.

Frequently asked questions

What Python version does aiokafka require?

Python 3.11 or newer. The readme states it plainly and the packaging metadata requires 3.11 or later, with classifiers for 3.11 through 3.14.

How do I use an aiokafka producer and consumer?

Construct a producer with bootstrap servers, await its start, use a send-and-wait call, and stop it in a finally block so pending messages are delivered or expire. For a consumer, pass topics and a group identifier, start it to join the group, iterate asynchronously, and stop it to leave the group and autocommit if enabled. Group load balancing requires a broker of version 1.0 or later.

Does aiokafka need a compiler to install?

No. It builds Cython extensions for record handling, but every extension is marked optional and the build command allows installation to fall back to the pure-Python implementation, so a failed compilation still yields a working install on the slower path.

Which compression codecs does aiokafka support?

There are extras for snappy, lz4, zstd and GSSAPI for Kerberos, plus an all extra. The lz4 extra notes that a specific version of the compression library is needed for independent-block mode support.

What does it take to run the aiokafka test suite?

Docker is required, plus Kerberos development packages on a Debian-family system, the lz4 development headers for Python, and a valid Java installation because some tests use the keytool utility to generate SSH keys. Tests run against a containerised Kafka whose version is selected by a make variable.

What licence is aiokafka released under?

Apache-2.0, with the version read from the package attribute rather than hardcoded. Version 0.14.0 was released on 2026-04-29 and the last push to the master branch was on 2026-09-10.

Official sources

  1. aio-libs/aiokafka on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/aio-libs-aiokafka.svg)](https://hysenlabs.com/projects/aio-libs-aiokafka)