Asynchrone taken en queues in PHP uitgelegd

Leer hoe asynchrone taken en queues in PHP werken. Praktische uitleg over workers, jobs en message brokers voor snellere applicaties in 2026.

17 juni 20267 min leestijdDoor We Develop Communication

Stel je voor dat een gebruiker op je webshop op "bestellen" klikt en vervolgens 15 seconden moet wachten omdat je applicatie een bevestigingsmail stuurt, een PDF-factuur genereert en de voorraad synchroniseert met een extern systeem. Dat is een slechte ervaring. Met asynchrone taken en queues in PHP los je dit op: zware klussen worden op de achtergrond uitgevoerd, terwijl de gebruiker direct een snelle response krijgt.

In dit artikel leer je hoe queues werken, welke drivers je kunt kiezen, en hoe je zelf jobs en workers opzet. Of je nu met Laravel werkt of een eigen PHP-applicatie bouwt: de principes blijven hetzelfde.

Waarom asynchrone taken belangrijk zijn

PHP is van oorsprong synchroon: elke regel code wordt na elkaar uitgevoerd. Een request komt binnen, de server verwerkt alles, en dan gaat de response terug. Dat werkt prima voor simpele pagina's, maar zodra je externe API's aanroept, grote bestanden verwerkt of e-mails verstuurt, merk je de beperking.

Een bezoeker wil niet wachten. Google straft trage responstijden af in je rankings, en conversiepercentages kelderen bij laadtijden boven de 3 seconden. Door werk naar de achtergrond te verplaatsen houd je je webapplicatie snel en schaalbaar.

Daarnaast maken queues je systeem betrouwbaarder. Valt een externe service uit? Dan blijft de job in de queue staan en wordt hij later opnieuw geprobeerd. Zonder queue zou je gebruiker een foutmelding krijgen.

Hoe een queue-systeem werkt

Een queue-systeem bestaat uit drie kerncomponenten die samen een pipeline vormen.

De producer (je applicatie)

De producer is het deel van je code dat een job toevoegt aan de queue. Dit gebeurt tijdens een normaal HTTP-request. In plaats van de taak direct uit te voeren, zeg je eigenlijk: "plaats deze klus op de stapel, iemand anders pakt hem later op."

De queue (de wachtrij)

De queue zelf is een opslagplek waar jobs wachten op uitvoering. Dit kan een Redis-list zijn, een RabbitMQ-exchange, een database-tabel of een cloud-service zoals Amazon SQS. Welke je kiest hangt af van je schaal en eisen.

De worker (de consumer)

De worker is een los PHP-proces dat continu draait en de queue leegt. Hij pakt jobs één voor één op, voert ze uit en markeert ze als voltooid. Als een job faalt, kan hij opnieuw geprobeerd worden of naar een "failed jobs"-tabel verhuizen.

Dit model vereist wel kennis van object-oriented PHP, omdat jobs meestal als classes worden gedefinieerd.

Queue-drivers vergeleken

Er zijn verschillende drivers waaruit je kunt kiezen. Elk heeft voor- en nadelen.

Database

De simpelste optie: jobs worden opgeslagen in een MySQL- of PostgreSQL-tabel. Dit werkt prima voor kleine projecten en vereist geen extra infrastructuur. Het nadeel is dat het traag wordt bij hoge volumes en extra druk op je database legt. Zie onze gids over PDO en databases voor de basis.

Redis

Redis is de meest populaire keuze voor PHP-queues. Het is razendsnel, eenvoudig op te zetten en ideaal voor de meeste webapplicaties. Het geheugengebruik is efficiënt en het integreert naadloos met Laravel, Symfony en andere frameworks. We schreven eerder over caching met Redis.

RabbitMQ

Voor enterprise-workloads met complexe routing, prioriteiten en message-patterns is RabbitMQ een solide keuze. Het ondersteunt het AMQP-protocol en biedt geavanceerde features zoals dead-letter queues en exchanges.

Amazon SQS

Als je op AWS draait, is SQS een goede managed-optie. Je hoeft zelf geen servers te beheren en het schaalt automatisch. Wel is de latency hoger dan bij Redis, en je betaalt per message.

Een job schrijven in Laravel

Laravel heeft out-of-the-box een uitstekend queue-systeem. Een job is simpelweg een class die een handle()-methode implementeert.

<?php

namespace App\Jobs;

use App\Mail\OrderConfirmation;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;

class SendOrderConfirmation implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $timeout = 60;

    public function __construct(public Order $order) {}

    public function handle(): void
    {
        Mail::to($this->order->customer_email)
            ->send(new OrderConfirmation($this->order));
    }
}

Het dispatchen naar de queue is één regel code:

SendOrderConfirmation::dispatch($order);

Wil je de job pas over 10 minuten uitvoeren? Gebruik dan ->delay(now()->addMinutes(10)).

Een worker draaien

Een job die netjes in de queue staat, doet niets zonder een worker. In Laravel start je een worker met:

php artisan queue:work redis --queue=default --tries=3 --timeout=90

In productie wil je deze niet handmatig starten. Gebruik daarvoor Supervisor op Linux, een procesmanager die crashende workers automatisch herstart. Een voorbeeld-configuratie:

[program:webshop-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/webshop/artisan queue:work redis --tries=3
autostart=true
autorestart=true
numprocs=4
user=www-data
stopwaitsecs=3600

Met numprocs=4 draaien er vier workers parallel, wat doorzet flink verhoogt bij piekbelasting.

Queues bouwen zonder framework

Werk je zonder Laravel? Dan kun je met Symfony Messenger of het losstaande package php-enqueue/enqueue een queue-systeem opzetten. De logica is hetzelfde: producer stuurt bericht, queue bewaart het, worker consumeert.

Een minimaal voorbeeld met Redis en de officiële predis/predis library:

<?php

// Producer: job aanbieden
$redis = new Predis\Client();
$redis->rpush('jobs:emails', json_encode([
    'to' => '[email protected]',
    'subject' => 'Bedankt voor je bestelling',
    'template' => 'order_confirmation',
]));

// Worker: jobs verwerken in een loop
while (true) {
    $payload = $redis->blpop(['jobs:emails'], 0);

    if ($payload === null) {
        continue;
    }

    $job = json_decode($payload[1], true);
    sendEmail($job['to'], $job['subject'], $job['template']);
}

Dit werkt, maar mist retry-logica, error handling en monitoring. Voor productie is een volwassen package beter.

Failed jobs en retries

Jobs falen. Een externe API is tijdelijk offline, een bestand is niet vindbaar, of er komt onverwachte data binnen. Goede queue-systemen bieden automatische retries met exponential backoff.

public int $tries = 5;
public array $backoff = [10, 30, 60, 120, 300];

Faalt de job ook na vijf pogingen? Dan komt hij in een "failed jobs"-tabel terecht, zodat je hem handmatig kunt inspecteren en opnieuw starten. Monitor deze tabel actief, een groeiende failed-jobs-tabel is vrijwel altijd een teken van een dieperliggend probleem.

Veelgebruikte use-cases

Queues zijn ideaal voor taken die:

  • Traag zijn: PDF-generatie, videoconversie, rapportages
  • Externe services aanroepen: e-mails, SMS, webhooks, betaalproviders
  • Periodiek uitgevoerd worden: dagelijkse exports, cleanup-taken
  • Geschikt zijn voor batch-verwerking: 10.000 nieuwsbrieven in één keer versturen
  • Opnieuw geprobeerd moeten kunnen worden: data-synchronisatie met flaky APIs

Een concreet voorbeeld: bij een geslaagde bestelling dispatch je meteen drie jobs: SendOrderConfirmation, GenerateInvoicePdf en NotifyWarehouse. De gebruiker krijgt binnen 200ms een bevestigingspagina, terwijl het echte werk op de achtergrond plaatsvindt.

Monitoring en observability

Een queue die je niet monitort, is een tijdbom. Gebruik tools zoals Laravel Horizon (voor Redis), RabbitMQ Management UI of CloudWatch (voor SQS) om real-time inzicht te krijgen in:

  • Aantal jobs in de queue
  • Doorzet per seconde
  • Faalpercentages
  • Gemiddelde uitvoertijd per job
  • Worker-status

Stel alerts in wanneer de queue-lengte een drempel overschrijdt. Dit voorkomt dat je pas ontdekt dat jobs zich ophopen wanneer klanten beginnen te klagen. Lees ook onze tips over performance optimalisatie voor meer handvatten.

Veelvoorkomende valkuilen

Grote payloads

Plaats geen volledige objecten of grote arrays in je job. Laravel serialiseert modellen automatisch naar ID's en haalt ze opnieuw op wanneer de worker de job uitvoert, precies wat je wilt.

Idempotentie

Queues garanderen "at-least-once"-delivery: een job kan in theorie twee keer uitgevoerd worden. Zorg dat je jobs idempotent zijn, zodat herhaalde uitvoering geen dubbele e-mails of dubbele betalingen veroorzaakt.

Geheugenlekken

PHP-workers draaien lang achter elkaar. Geheugen dat niet vrijgegeven wordt stapelt zich op. Beperk daarom de levensduur met --max-jobs=1000 of --max-time=3600, zodat Supervisor de worker periodiek herstart.

Timezone- en serialisatieproblemen

Zorg dat je worker dezelfde configuratie heeft als je webserver: dezelfde PHP-versie, .env-waardes en tijdzone. Anders krijg je verwarrende bugs.

Veelgestelde vragen

Wat zijn asynchrone taken in PHP?

Asynchrone taken zijn stukjes werk die niet direct tijdens een HTTP-request worden uitgevoerd, maar op de achtergrond door een aparte worker. Dit maakt je applicatie sneller en responsiever voor de gebruiker.

Wat is een queue in PHP?

Een queue is een wachtrij waarin jobs worden geplaatst totdat een worker ze oppakt en uitvoert. Veelgebruikte queue-systemen in PHP zijn Redis, RabbitMQ, Amazon SQS en database-driven queues.

Wanneer gebruik je een queue?

Gebruik een queue voor taken die traag zijn, onbetrouwbare externe diensten aanroepen of op een later moment uitgevoerd kunnen worden. Denk aan e-mails versturen, afbeeldingen verwerken, rapportages genereren of webhooks afhandelen.

Wat is het verschil tussen een job en een worker?

Een job is de taak die uitgevoerd moet worden, bijvoorbeeld het versturen van een e-mail. Een worker is het proces dat continu de queue leegt en de jobs daadwerkelijk uitvoert.

Welke queue-driver kies je het beste?

Voor de meeste projecten is Redis een uitstekende keuze vanwege de snelheid en eenvoud. Voor zware enterprise-workloads kies je RabbitMQ of Amazon SQS, en voor kleine projecten volstaat een database-driver.

Conclusie

Asynchrone taken en queues zijn geen luxe, maar een noodzaak voor moderne PHP-applicaties. Ze houden je responstijden laag, maken je systeem betrouwbaarder en zorgen dat piekbelasting geen crashende server oplevert.

Begin klein: verplaats eerst e-mails en zware externe API-calls naar een queue. Meet het verschil in responstijd, en breid langzaam uit. Voor je het weet draait je applicatie soepel, ook wanneer het druk wordt. Succes met bouwen.

Veelgestelde vragen

Klaar om digitaal te groeien?

Wij helpen Nederlandse bedrijven met webtechnologie en SEO-strategieën die écht werken. Neem vrijblijvend contact op.