Async PHP
Data Processing
Multisystem Integration
PHP Tips
Asynchronous Programming

Async PHP Processing data into several systems Advice

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When one PHP application has to push the same business event into several external systems, the biggest risk is usually not raw execution time. The real risk is partial success: one system succeeds, another times out, and the request ends with no clear record of what still needs to be delivered.

That is why the best advice is usually architectural rather than syntactic. Instead of trying to do every integration call directly inside the user request, persist the event first and let background workers deliver it reliably.

Start with a Queue or Outbox Pattern

If a web request must update a database, notify a CRM, send analytics, and publish a message to another service, do not make the browser wait for all of that. Persist the core business action, then record follow-up work in an outbox table or queue.

A small SQLite outbox example is enough to show the pattern:

php
1<?php
2$db = new PDO('sqlite:app.db');
3$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
4
5$db->exec('CREATE TABLE IF NOT EXISTS outbox (
6    id INTEGER PRIMARY KEY AUTOINCREMENT,
7    event_type TEXT NOT NULL,
8    payload TEXT NOT NULL,
9    status TEXT NOT NULL DEFAULT "pending"
10)');
11
12$payload = json_encode([
13    'order_id' => 123,
14    'customer_email' => '[email protected]'
15], JSON_THROW_ON_ERROR);
16
17$stmt = $db->prepare('INSERT INTO outbox (event_type, payload) VALUES (?, ?)');
18$stmt->execute(['order.created', $payload]);
19
20echo "Event recorded for async processing\n";

This request finishes quickly while still preserving the work that needs to happen later.

Process Each Target System in a Worker

A background worker can pull pending events and deliver them one by one. The example below prints destinations instead of calling real APIs, but the structure is the important part.

php
1<?php
2$db = new PDO('sqlite:app.db');
3$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
4
5$rows = $db->query('SELECT id, event_type, payload FROM outbox WHERE status = "pending"')
6          ->fetchAll(PDO::FETCH_ASSOC);
7
8foreach ($rows as $row) {
9    $payload = json_decode($row['payload'], true, 512, JSON_THROW_ON_ERROR);
10
11    foreach (['crm', 'analytics', 'billing'] as $target) {
12        echo "Sending {$row['event_type']} to {$target} for order {$payload['order_id']}\n";
13    }
14
15    $stmt = $db->prepare('UPDATE outbox SET status = "done" WHERE id = ?');
16    $stmt->execute([$row['id']]);
17}

In production, each target call would need retry rules, timeout handling, and durable logging.

Make Every Delivery Idempotent

Once you move to asynchronous workers, retries are normal. That means the receiving systems must tolerate repeated delivery of the same event. Use stable identifiers such as order IDs or event IDs so the receiver can detect duplicates.

Without idempotency, a retry might create duplicate invoices, duplicate emails, or duplicate CRM records. That is usually more dangerous than the original timeout.

Split the Problem by Failure Boundary

Not every downstream system deserves the same treatment. Classify them:

  • critical systems that must eventually succeed
  • best-effort systems such as analytics
  • slow systems that should never block the user request
  • systems that can accept batched delivery

This classification helps you decide whether to use one queue, several queues, or different worker priorities.

Async Libraries Help, but They Are Not the First Decision

Libraries such as ReactPHP, Amp, or Swoole can help when a single worker needs to overlap I/O efficiently. They are useful, but they do not replace durable workflow design.

If the architecture is wrong, async I/O just makes failures happen faster. Start with persistence, retryability, and idempotency. Then optimize worker throughput if the volume justifies it.

Common Pitfalls

  • Calling several remote systems inline during the user request.
  • Treating async execution as a substitute for durable job tracking.
  • Retrying failed deliveries without idempotent identifiers.
  • Sending all external calls through one worker with no priority or failure separation.
  • Optimizing library choice before defining the reliability model.

Summary

  • For multi-system processing in PHP, persist the event first and deliver it asynchronously.
  • An outbox or queue is usually a better starting point than direct parallel API calls.
  • Workers should handle retries, timeouts, and status tracking.
  • Idempotency is mandatory once retries are involved.
  • Async frameworks are useful after the delivery architecture is reliable.

Course illustration
Course illustration

All Rights Reserved.