• Start

Languages

/

PHP

/

v2 (alpha)

/

Concepts

Runtimes and workers

Configure your PHP environment (PHP-FPM, OpenSwoole, or FrankenPHP) so live queries and other long-lived connections run without blocking your application.

By default the SDK runs on the standard synchronous PHP runtime. That suits request and response work: connect, run a query, return a result. Long-lived operations such as live queries block the process that runs them until they end, so they need a runtime and worker setup that keeps the rest of your application responsive.

This page covers three setups: PHP-FPM with dedicated workers, OpenSwoole, and FrankenPHP.

The Runtime helper returns a DriverOptions preset that you pass to new Surreal(...). It wires up the matching scheduler and transports.

use SurrealDB\SDK\Surreal;
use SurrealDB\SDK\Runtime\Runtime;

$db = new Surreal(Runtime::sync()); // default, synchronous
$db = new Surreal(Runtime::swoole()); // OpenSwoole coroutines
$db = new Surreal(Runtime::amp()); // Amp / Revolt event loop

The Swoole and Amp presets rely on optional packages, so install the matching dependency (listed under suggest in the SDK's composer.json) before using them.

Each preset optionally accepts an ObservabilityOptions to wire OpenTelemetry with the export strategy that fits the runtime: the synchronous preset buffers spans and flushes after the request, while the async presets export directly through a non-blocking transport.

use SurrealDB\SDK\Surreal;
use SurrealDB\SDK\Runtime\Runtime;
use SurrealDB\SDK\Telemetry\OpenTelemetry\ObservabilityOptions;

$db = new Surreal(Runtime::sync(
observability: new ObservabilityOptions(serviceName: 'my-app'),
));

See Observability for the full setup and options.

PHP-FPM is the common setup behind Nginx or Apache. Its pool serves web requests, and each worker handles one request at a time on the synchronous runtime. That is fine for queries and mutations, but a live query would hold a worker open indefinitely and eventually exhaust the pool.

Keep PHP-FPM for the web tier, and run live queries in separate, long-running CLI workers.

Tune the pool in your PHP-FPM config (for example www.conf) so the web tier has enough workers for your traffic.

pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8

Put the live query loop in a CLI script.

worker.php

require __DIR__ . '/vendor/autoload.php';

use SurrealDB\SDK\Surreal;
use SurrealDB\SDK\Connection\ConnectOptions;

$db = new Surreal();
$db->connect('ws://127.0.0.1:8000/rpc', new ConnectOptions(
namespace: 'surrealdb',
database: 'docs',
));

[$queryId] = $db->run('LIVE SELECT * FROM person');

foreach ($db->live($queryId) as $message) {
// handle $message->action and $message->value
}

Run several copies under a process manager so that one worker blocked on a live query never affects the others. With Supervisor, the numprocs setting controls how many processes run in parallel.

/etc/supervisor/conf.d/surreal-live.conf

[program:surreal-live]
command=php /var/www/app/worker.php
numprocs=4
process_name=%(program_name)s_%(process_num)02d
autostart=true
autorestart=true
stopwaitsecs=10

A systemd template unit achieves the same. Define surreal-live@.service, then start as many instances as you need with systemctl start surreal-live@{1..4}.

OpenSwoole adds a coroutine runtime, so a single process can drive many concurrent tasks, including live queries, on an event loop without blocking.

Install the extension with PECL and enable it in your php.ini.

pecl install openswoole

Run your code inside a coroutine context and use the Swoole preset. The preset enables OpenSwoole's runtime hooks so the SDK's connection becomes non-blocking.

use OpenSwoole\Coroutine as Co;
use SurrealDB\SDK\Surreal;
use SurrealDB\SDK\Connection\ConnectOptions;
use SurrealDB\SDK\Runtime\Runtime;

Co::run(function (): void {
$db = new Surreal(Runtime::swoole());
$db->connect('ws://127.0.0.1:8000/rpc', new ConnectOptions(
namespace: 'surrealdb',
database: 'docs',
));

[$queryId] = $db->run('LIVE SELECT * FROM person');

foreach ($db->live($queryId) as $message) {
// other coroutines keep running while this waits
}
});

In an OpenSwoole HTTP server, set the number of worker processes with the worker_num server setting.

FrankenPHP runs PHP as a long-lived application server. In worker mode the app stays booted between requests, and the Amp / Revolt event loop lets the SDK process live queries without blocking. Install revolt/event-loop and the Amp packages (see the SDK's composer.json suggestions), then use the Amp preset.

use SurrealDB\SDK\Surreal;
use SurrealDB\SDK\Runtime\Runtime;

$db = new Surreal(Runtime::amp());

Enable worker mode and set the worker count in your Caddyfile or through the environment variable. The trailing number is the number of workers.

FRANKENPHP_CONFIG="worker ./public/index.php 4"

Was this page helpful?