Install PHP rdkafka on Windows: PHP 8.3 & Laravel Guide

Avatar
M

Maksudur Rahman

Software Engineer

70Views
5mRead
0Reactions

When integrating Apache Kafka into a Laravel application on Windows, running composer install or adding packages like mateusjunges/laravel-kafka often halts with a blocking platform error:

Problem 1
  - mateusjunges/laravel-kafka v2.9.0 requires ext-rdkafka ^6.0
  - it is missing from your system. Install or enable PHP's rdkafka extension.

Simply downloading php_rdkafka.dll and copying it to your PHP ext/directory usually results in another deceptive warning: PHP Warning: PHP Startup: Unable to load dynamic library 'rdkafka' - The specified module could not be found.

This guide walks through configuring the PHP rdkafka extension on Windows with PHP 8.3, placing the required native C dependencies, troubleshooting dynamic linker errors in Laragon or native PHP environments, and verifying Kafka event publishing in Laravel.

Quick Summary / Prerequisites

flowchart LR
    subgraph App_Layer["Application Layer"]
        Laravel["Laravel Application"]
        Pkg["mateusjunges/laravel-kafka"]
    end
    subgraph PHP_Runtime["PHP 8.3 Runtime"]
        Ext["ext-rdkafka\n(php_rdkafka.dll in php/ext/)"]
    end
    subgraph OS_Layer["Windows OS & C Dependencies"]
        Native["Native C Engine\n(librdkafka.dll in root php/)"]
    end
    subgraph Broker["Message Broker"]
        Kafka[("Apache Kafka Cluster\n:9092")]
    end

    Laravel --> Pkg
    Pkg --> Ext
    Ext --> Native
    Native -->|TCP Protocol| Kafka
  • Operating System: Windows 10 / Windows 11 / Windows Server (x64)

  • PHP Version: PHP 8.3.x (Non-Thread-Safe or Thread-Safe)

  • Local Environment: Laragon, XAMPP, or standalone PHP CLI

  • Required Extension: php_rdkafka.dll (PECL 6.x+)

  • Required Native Library: librdkafka.dll

The Root Cause: Why "php_rdkafka.dll" Alone Fails

The rdkafka PHP extension is not a standalone PHP wrapper. It is a thin C-binding interface that delegates all socket connections, message batching, compression, and CRC checksum calculations to librdkafka—the official high-performance C/C++ client library for Apache Kafka.

When PHP loads php_rdkafka.dll on Windows, the Windows Dynamic-Link Library (DLL) loader attempts to resolve its internal dependency on librdkafka.dll. If librdkafka.dll is missing from the directory containing php.exe or from the system PATH, the OS fails the load operation. PHP then reports that rdkafka cannot be found—even though php_rdkafka.dll is sitting directly inside your ext/directory.

Step 1: Identifying Your PHP Build Configuration

Before downloading any DLL binary, determine the exact compilation signature of your active PHP runtime. Installing a Thread-Safe (TS) binary on a Non-Thread-Safe (NTS) PHP build, or mismatching Visual C++ compiler versions (e.g., VS16 vs VS17), will cause PHP to silently reject the module.

Open PowerShell or Windows Terminal and run:

php -v

Next, locate your active php.ini file:

php --ini

Extract the architecture, thread safety, and compiler version:

php -i | Select-String -Pattern "Architecture|Thread Safety|Compiler"

Understanding the Output

Parameter

Example Value

Required DLL Match

Architecture

x64

Must download x64 (not x86)

Thread Safety

disabled (NTS)

Must download NTS (common in Laragon/Nginx)

Thread Safety

enabled (TS)

Must download TS (common in Apache mod_php)

Compiler

Visual C++ 2019 or VS16

Must match VS16 build binaries

For a standard Laragon installation running PHP 8.3, your PHP path resembles:

C:\laragon\bin\php\php-8.3.10-nts-Win32-vs16-x64

Step 2: Downloading Compatible rdkafka and librdkafka Binaries

Windows binaries for PECL extensions are packaged as.zip archives containing both the PHP extension DLL and the native runtime dependencies.

  1. Navigate to the official PECL rdkafka Package Page or the official Windows PECL releases.

  2. Select the latest stable release (e.g., 6.0.5 for PHP 8.3).

  3. Choose the build that matches your Step 1 signature:

    • PHP 8.3 Non-Thread-Safe (NTS) x64: php_rdkafka-6.0.5-8.3-nts-vs16-x64.zip

    • PHP 8.3 Thread-Safe (TS) x64: php_rdkafka-6.0.5-8.3-ts-vs16-x64.zip

  4. Extract the.zip archive to a temporary directory.

Inside the extracted archive, you will find two critical files:

  • php_rdkafka.dll (The PHP extension)

  • librdkafka.dll (The native C library)

Step 3: Installing php_rdkafka.dll and librdkafka.dll

Place each DLL into its required location inside your PHP installation directory.

C:\laragon\bin\php\php-8.3.10-nts-Win32-vs16-x64\
├── php.exe
├── php.ini
├── librdkafka.dll          <-- MUST be in the root PHP folder (beside php.exe)
│
└── ext\
    ├── php_curl.dll
    ├── php_openssl.dll
    └── php_rdkafka.dll      <-- Placed inside the ext/ directory

Moving the Files with PowerShell

Run the following commands in PowerShell (adjust the path to match your PHP directory):

# Define your PHP base directory
$phpDir = "C:\laragon\bin\php\php-8.3.10-nts-Win32-vs16-x64"

# 1. Copy the PHP extension DLL into ext/
Copy-Item ".\extracted\php_rdkafka.dll" -Destination "$phpDir\ext\" -Force

# 2. Copy the native C dependency into the root PHP directory
Copy-Item ".\extracted\librdkafka.dll" -Destination "$phpDir\" -Force

Verify that both files are present:

Test-Path "$phpDir\ext\php_rdkafka.dll"
Test-Path "$phpDir\librdkafka.dll"

Both checks must return True.

Step 4: Enabling the Extension in php.ini

Open your active php.ini file:

notepad "C:\laragon\bin\php\php-8.3.10-nts-Win32-vs16-x64\php.ini"

Scroll to the Dynamic Extensions section and add the extension directive:

; Extension directive for rdkafka
extension=rdkafka

[!NOTE] In modern PHP (7.2+ and 8.x), specifying extension=rdkafka without the.dll suffix is standard. PHP automatically appends.dll on Windows.

Confirm that the entry exists and is not duplicated or commented out:

Select-String -Path "$phpDir\php.ini" -Pattern "rdkafka"

Expected output:

C:\laragon\bin\php\php-8.3.10-nts-Win32-vs16-x64\php.ini:952:extension=rdkafka

Step 5: Verifying PHP CLI and Module Loading

Before touching Composer or Laravel, verify that the PHP engine successfully loads the module in the CLI environment.

1. Check Loaded Modules

php -m | Select-String -Pattern "rdkafka"

Expected output:

rdkafka

2. Inspect Extension Information & Version

php --ri rdkafka

This output displays the compiled librdkafka version, supported compression codecs (snappy, zstd, gzip), and SASL security features:

rdkafka

rdkafka extension => enabled
version => 6.0.5
librdkafka version (runtime) => 2.3.2
librdkafka version (build) => 2.3.2

3. Evaluate via Runtime Expression

php -r "var_dump(extension_loaded('rdkafka'));"

Output:

bool(true)

If you use a local web server (such as Nginx or Apache inside Laragon), restart the services now so PHP FastCGI (php-cgi.exe) workers inherit the new configuration.

Step 6: Running Composer Install and Testing Laravel Kafka

Once PHP CLI detects ext-rdkafka, Composer can resolve package dependencies without triggering platform mismatch warnings.

In your Laravel project root:

composer install

Composer will now successfully install mateusjunges/laravel-kafka:

Installing mateusjunges/laravel-kafka (v2.9.0): Extracting archive
Generating optimized autoload files

Why You Should Never Rely on--ignore-platform-req=ext-rdkafka

When ext-rdkafka is missing, Composer suggests running:

composer install --ignore-platform-req=ext-rdkafka

This flag only bypasses the Composer dependency tree check. It does not make Kafka work. As soon as your Laravel code attempts to instantiate a producer or consumer, the script crashes at runtime:

Fatal error: Uncaught Error: Class "RdKafka\Producer" not found

Treat--ignore-platform-req as a debugging tool for CI environments that do not execute Kafka code, never as a local development fix.

Step 7: Writing a Producer Test in Laravel

To ensure the native librdkafka engine can open socket connections and produce messages to your Kafka broker, create a test Artisan command.

Create app/Console/Commands/TestKafkaProducer.php:

<?php

declare(strict_types=1);

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Junges\Kafka\Facades\Kafka;
use Junges\Kafka\Message\Message;
use Throwable;

class TestKafkaProducer extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'kafka:test-produce {topic=order-events}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Dispatch a test message to an Apache Kafka topic';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $topic = (string) $this->argument('topic');

        $this->info("Initializing Kafka producer for topic: [{$topic}]...");

        $payload = [
            'event_id'   => fake()->uuid(),
            'event_type' => 'order.created',
            'amount'     => 149.99,
            'currency'   => 'USD',
            'timestamp'  => now()->toIso8601String(),
        ];

        $message = new Message(
            headers: ['source' => 'laravel-backend', 'version' => '1.0'],
            body: $payload,
            key: 'order-key-101'
        );

        try {
            /** @var \Junges\Kafka\Producers\ProducerBuilder $producer */
            $producer = Kafka::publishOn($topic)
                ->withMessage($message)
                ->withConfigOptions([
                    'compression.codec'     => 'snappy',
                    'socket.timeout.ms'     => 5000,
                    'message.timeout.ms'    => 10000,
                    'queue.buffering.max.ms' => 50,
                ]);

            $producer->send();

            $this->info("✓ Message successfully dispatched to Kafka!");
            $this->line(json_encode($payload, JSON_PRETTY_PRINT));

            return self::SUCCESS;
        } catch (Throwable $e) {
            $this->error("Failed to produce message: " . $e->getMessage());

            return self::FAILURE;
        }
    }
}

Run the command in your terminal:

php artisan kafka:test-produce order-events

Troubleshooting Diagnostic Workflow

If PHP continues to throw startup warnings or fails to load rdkafka, follow this systematic diagnostic flowchart:

flowchart TD
    Start([PHP Fails to Load rdkafka]) --> Q1{Does php_rdkafka.dll exist in ext/?}
    Q1 -- No --> Fix1[Copy php_rdkafka.dll into php/ext/]
    Q1 -- Yes --> Q2{Is librdkafka.dll in the root PHP folder?}
    
    Q2 -- No --> Fix2[Copy librdkafka.dll to the root PHP folder next to php.exe]
    Q2 -- Yes --> Q3{Does DLL Architecture & Thread Safety match php -i?}
    
    Q3 -- No --> Fix3[Download correct x64 / NTS vs TS build from PECL]
    Q3 -- Yes --> Q4{Is Visual C++ 2015-2022 Redistributable installed?}
    
    Q4 -- No --> Fix4[Install VC++ vcredist_x64.exe from Microsoft]
    Q4 -- Yes --> Q5{Did you restart terminal & Laragon services?}
    
    Q5 -- No --> Fix5[Restart PowerShell & Laragon Web/FPM processes]
    Q5 -- Yes --> Done([Run: php -m | findstr rdkafka -> Success!])

    Fix1 --> Done
    Fix2 --> Done
    Fix3 --> Done
    Fix4 --> Done
    Fix5 --> Done

Common Errors & Direct Fixes

1. Warning: PHP Startup: Unable to load dynamic library 'rdkafka' (The specified module could not be found)

  • Cause: librdkafka.dll is missing from the directory containing php.exe, or the Visual C++ Redistributable (x64) is not installed.

  • Fix: Copy librdkafka.dll into C:\laragon\bin\php\php-8.3.x\(alongside php.exe). Install the latest Microsoft Visual C++ 2015–2022 Redistributable (x64).

2. Module 'rdkafka' is already loaded in Unknown on line 0

  • Cause: extension=rdkafka is declared more than once across your php.ini file or in individual conf.d extension files.

  • Fix: Run Select-String -Path "$phpDir\php.ini" -Pattern "rdkafka"and remove duplicate declarations.

3. CLI shows rdkafka loaded, but Web/phpinfo() does not show it

  • Cause: Laragon or your web server uses a separate php.ini file or different PHP binary for Apache/Nginx FastCGI than your CLI terminal.

  • Fix: Run php --ini inside a web script (<?php phpinfo(); ?>) to inspect the loaded configuration path, then add extension=rdkafka to that specific php.ini.

Pro-Tips for High-Throughput Laravel Kafka Systems

  1. Optimize Producer Flush Times: High-frequency web requests should not block waiting for Kafka broker acknowledgments. Configure'queue.buffering.max.ms' => 20 and dispatch heavy production workloads through asynchronous Laravel job queues. For database performance optimizations alongside event processing, explore our guide on preventing N+1 queries in Laravel database workloads.

  2. Isolate Runtime Configurations: If you connect to multiple Kafka clusters with distinct SASL credentials across different tenants, avoid mutating global environment state. Use service providers and dynamic configuration objects, similar to the architecture detailed in our dynamic SMTP mail configuration tutorial.

  3. Containerized Deployments: While local Windows development requires manual DLL placement, production microservices should run in Linux container environments. See our guide on configuring Docker Compose and reverse proxies for production deployment patterns.

FAQ

Why does Composer say ext-rdkafka is missing even after adding php_rdkafka.dll?

PHP rdkafka depends on the native librdkafka.dll C library. If librdkafka.dll is not placed in your root PHP directory or added to the Windows PATH, PHP fails to load the extension with"The specified module could not be found".

Can I use --ignore-platform-req=ext-rdkafka as a permanent fix?

No. Ignoring the platform requirement only bypasses Composer's dependency check during install. When your Laravel application executes Kafka producers or consumers, it will crash with a fatal Class "RdKafka\Producer" not found error.

How do I verify if the rdkafka extension is loaded in PHP CLI?

Run php -m | findstr /i rdkafka in PowerShell or Command Prompt, or run php -r "var_dump(extension_loaded('rdkafka'));"to verify it returns bool(true).

How do I choose between NTS and TS versions of php_rdkafka.dll?

Run php -i | findstr /i "Thread Safety". If Thread Safety is disabled, use Non-Thread-Safe (NTS) DLLs (common in Laragon/Nginx). If enabled, use Thread-Safe (TS) DLLs (common in Apache mod_php).

Hope, it solved your problem. Thank you for reading.

Recommended Resources & Courses

React to this article