Open-source project
php-rdkafka/php-rdkafka avatar
php-rdkafka/php-rdkafka

php-rdkafka: a deliberately thin PHP binding to librdkafka, with a README that argues for it

Production-ready, stable Kafka client for PHP

2,180 stars276 forksCMIT

At a glance

What is it?
2,180 stars for a C extension that refuses to add opinions. The install instructions live off the README, the low level consumer is legacy, and the badges describe a version line the project has moved past.
Who is it for?
php-rdkafka is a good fit when you want Kafka's own semantics rather than a framework's idea of them, because it hands you librdkafka's configuration keys, delivery guarantees and shutdown rules without reshaping them. The costs are visible in the README: there is no install command on the page itself, the most documented code paths are flagged legacy, and two thirds of the badge line describes support ranges the current version has already narrowed.
Can I use it commercially?
Yes. MIT 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 34 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

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

Editorial analysis

The stated goal is to have no opinions

The README states the goal plainly: a low level, unopinionated librdkafka binding focused on production and long term support. That is a design position, not a feature list, and it explains most of what the project looks like.

The surface area is the producer, the high level and low level consumers, and the metadata APIs. Configuration is passed as string keys that are the librdkafka configuration reference verbatim, so anything in that document is available and anything the README says about a parameter is the library's own documentation restated. The extension is written in C, MIT licensed, at 2,180 stars and 276 forks, with 14 open issues and a last push on 2026-09-08.

The repository layout matches a C extension written to a book. Each class has a `.c`, a `.h`, a `.stub.php` and an `_arginfo.h`, so `kafka_consumer.c`, `message.c`, `metadata_broker.c`, `metadata_partition.c`, `metadata_topic.c` and `oauthbearer.c` each declare a typed surface to the engine. The presence of stub files alongside the hand written ones is the tell that this targets modern PHP extension conventions rather than the older parameter parsing style.

The badges describe a wider support range than the project currently claims

The badge line and the prose under it disagree, and the prose is the current one. The badges advertise librdkafka 0.11 or newer, Kafka 0.8 or newer, and PHP 7.x through 8.x. The paragraph immediately below says the current version supports PHP 8.1.0 or newer, librdkafka 1.5.3 or newer, and Kafka 0.8, then adds that version 6.x supports PHP 7.x to 8.x with librdkafka 0.11 through 2.x, and that older versions supported PHP 5.

So the badges describe the 6.x compatibility window while the body describes the current major line. Both are true of the repository as a whole, because the 6.x branch still exists and is documented in the body itself, but a reader who installs from the badge line expectations and lands on the current version will find PHP 8.0 and librdkafka 1.5.0 are below the floor.

There is a third data point worth noting. The most recent release in the list is 6.0.5 from 2024-11-04, while the repository was pushed on 2026-09-08. That gap of close to two years says the version numbering in the prose is describing a line the project intends rather than one it has published a tarball for, so anyone verifying the actual current release should look at the release page rather than at the README sentence.

Producing is three methods, and shutdown is the part you will get wrong

The producer path is the clearest tutorial in the README. Create a configuration object, add brokers, create a topic, produce.

``` php <?php $conf = new RdKafka\Conf(); $conf->set('log_level', (string) LOG_DEBUG); $conf->set('debug', 'all'); $rk = new RdKafka\Producer($conf); $rk->addBrokers("10.0.0.1:9092,10.0.0.2:9092");

code

The `produce` call takes a partition first, where the unassigned constant lets librdkafka choose, then message flags that are either zero or the blocking flag, then the payload.

php <?php

$topic->produce(RD_KAFKA_PARTITION_UA, 0, "Message payload");

code

What the README emphasises, in a warning block and again in prose, is shutdown. Queued and in-flight produce requests must complete before the producer is destroyed, which is what the flush call is for, and the README states flatly that not calling it can lead to message loss. There is also a purge call for discarding unsent messages before flushing, with the explicit use case of a producer that does not care about them.

php $rk->flush($timeout_ms); ```

That is the whole producer contract. There is no retry logic, no idempotence helper and no delivery callback wiring in the README, which is the unopinionated position taken literally: delivery guarantees are librdkafka's configuration, not the extension's abstraction.

Most of the documented consume code is labelled legacy

The consumer story is where the README's shape is most confusing, and the confusion is honest. It points at the high level consumer class as supporting automatic partition assignment and revocation, and links the example page. Then it spends several sections documenting the low level consumer, twice marking each section as a legacy API with a note to prefer the high level one.

The legacy walkthrough creates a consumer, adds brokers, creates a topic and starts consuming on a partition from a named offset, where the valid values are beginning, end and stored.

``` php <?php

$topic = $rk->newTopic("test");

// The first argument is the partition to consume from. // The second argument is the offset at which to start consumption. Valid values // are: RD_KAFKA_OFFSET_BEGINNING, RD_KAFKA_OFFSET_END, RD_KAFKA_OFFSET_STORED. $topic->consumeStart(0, RD_KAFKA_OFFSET_BEGINNING); ```

Then it loops on consume with a timeout and checks two conditions. There is a null check alongside a partition-end error check, and the comment explains why both are needed: a constant check is required by librdkafka 0.11.6, while newer versions return null instead. That comment is a small fossil of the library's own history, and it is the kind of detail that only appears when someone has read the code rather than the documentation.

Multi-topic and multi-partition consumption on the legacy API is done by forwarding everything to an internal queue and consuming from that. Whether you should use it at all is answered twice in the same document: prefer the high level consumer.

The test environment runs ZooKeeper and an old broker

The `docker-compose.yml` at the repository root is more informative about the project's testing than anything in the README. It defines a build environment service that builds from a Dockerfile under `.docker/` with PHP 8.3 and mounts the source, plus a ZooKeeper service and a Kafka service, both from the `wurstmeister` project using the `latest` tag.

The Kafka service sets `TEST_KAFKA_BROKER_VERSION` to 2.6 in the test environment, and its topic configuration creates a topic named `test-topic` with a cleanup policy of compact. The README's own examples use a topic named `test` with no such suffix, so the compose file and the documentation are working with different topic names. For anyone copying a README example into the bundled environment, that difference will surface as an auto-created topic rather than the expected one.

More interesting is ZooKeeper. A ZooKeeper dependency describes a Kafka deployment mode that the Kafka project has been moving away from, and pairing it with a pinned broker version of 2.6 suggests the compose file was written for the era when that was the current release. An OAuth-capable second broker is also defined, on a separate port with a network alias, gated behind a compose profile because it is only needed for the OAuth bearer integration tests.

That last detail is a good sign about the project's rigour: the OAuth path added in 6.0.4 is tested against a real broker configured for it, not mocked.

Two documentation domains, and installation is not on the page

The README's Installation and Examples sections contain no content. Each is a single line pointing at a documentation site, and the two sites are different: the repository metadata sets the homepage to the `php-rdkafka.github.io` domain, while the README links install and examples under the `arnaud-lb.github.io` path and the main documentation under a third path with a book-style URL.

That split is the single biggest practical fact about the project. The README is a usage sketch for people who already have the extension installed. Getting it installed means compiling a C extension against librdkafka, which in practice means a PECL install with the right headers present, or a container image, and neither route is described on the repository page.

What the README does supply is the interesting configuration guidance, which is the part that rewards reading. Three parameters get their own subsections: the queue memory cap, the sparse metadata refresh behaviour with its interval, and the internal termination signal, which lets librdkafka shut down cleanly on a signal instead of being killed. These are the settings that decide whether a PHP process exits without dropping queued messages, and they are exactly the knobs an unopinionated binding should expose and explain.

A chat badge at the top of the README points at Gitter, a service that has since been wound down, which is the most obvious piece of the page that has aged.

Editorial conclusion

php-rdkafka is a good fit when you want Kafka's own semantics rather than a framework's idea of them, because it hands you librdkafka's configuration keys, delivery guarantees and shutdown rules without reshaping them. The costs are visible in the README: there is no install command on the page itself, the most documented code paths are flagged legacy, and two thirds of the badge line describes support ranges the current version has already narrowed. If you are starting fresh, read the linked installation page, use the high level consumer rather than the legacy one, and make sure your shutdown path calls flush, because the README warns twice that skipping it loses messages. Pin your librdkafka version deliberately; the extension follows that library's compatibility rules, not its own.

Frequently asked questions

What PHP versions does php-rdkafka support?

The README text is more current than the badge on the same page. It states that the current version needs PHP 8.1.0 or newer with librdkafka 1.5.3 or newer, while version 6.x covers PHP 7.x through 8.x with librdkafka 0.11 through 2.x, and still older releases covered PHP 5. Check which major line you are installing before trusting the badge.

What is PHP used for in this project?

PHP is the language the extension exposes to. The repository is C source that compiles into a PHP extension, so PHP code constructs configuration objects, producers, topics and consumers, and calls methods on them. Each exposed class ships a stub file so the API is typed for modern PHP tooling.

Why do my produced messages disappear when the PHP script ends?

The README warns twice that a producer must be shut down properly, because queued and in-flight produce requests are only completed during a flush. Call the flush method with a reasonable timeout before the producer is destroyed. If unsent messages do not matter, purge the queue first and then flush.

Should I use the high level or low level Kafka consumer?

The high level consumer, which supports automatic partition assignment and revocation. The README marks the low level consumer sections as a legacy API and tells readers twice to prefer the high level one, even though most of the documented example code covers the legacy path.

Official sources

  1. License: MIT
  2. php-rdkafka/php-rdkafka on GitHub
  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/php-rdkafka-php-rdkafka.svg)](https://hysenlabs.com/projects/php-rdkafka-php-rdkafka)