Extension Limits
Winter Boot leans on a small set of PHP extensions. This page lists what each one is needed for and, more importantly, what happens when it is absent or misconfigured — so a missing extension shows up as an understood error, not a mystery. The startup banner prints the detected version (or not installed) for Swoole, rdkafka and redis on every boot; check it first when something extension-related misbehaves.
Need anything else (for example memcache or opentelemetry)? Extend the image with your own multi-stage build rather than installing into it — that keeps the runtime image small. See the Dockerfile for the builder pattern to follow.
The sections below then apply only to setups that do not use this image.
Swoole (required for server, async and coroutines)
Section titled “Swoole (required for server, async and coroutines)”Web applications run on the Swoole server (WinterWebSwooleApplication), and all concurrency features build on it.
- Async and scheduling refuse to boot without it. Using
#[EnableAsync],#[EnableScheduling],#[Async]or#[Scheduled]without the extension throws anAnnotationExceptionduring startup naming the offending class or method. There is no silent fallback — remove the annotation or install Swoole. - Daemon threads need it.
#[DaemonThread]workers are Swoole processes; without the extension they cannot start. - Never read request state from superglobals. Under Swoole, worker processes are shared across requests:
$_SERVER,$_COOKIEand thesession_*functions can carry values belonging to another request. Always read through the injectedHttpRequest(getQueryParam(),getCookie(),getFirstHeader(), …) and manage sessions viaSessionManager. - Graceful degradation where it is safe. Coroutine-scoped connection pools and request detection quietly fall back to non-coroutine behavior when Swoole (or its
Coroutine/Channelclasses) is unavailable — pooling still works, just without coroutine isolation.
winter_boot (required since 2.1.0, native capabilities)
Section titled “winter_boot (required since 2.1.0, native capabilities)”The bundled native extension. Booting without it stops the application with a clear error — use the runtime Docker image, where it is preinstalled, instead of assembling it yourself. See Native Extension for full usage; the limits in brief:
- Throws
Erroroutside a function body (global/file/evalscope) and inside generator functions (usetry/finallythere instead). - Throws
TypeErrorfor a non-callable argument. - Fully supported inside fibers;
Fiber::suspend()never triggers callbacks. - Pending callbacks are discarded — never executed — on fatal errors (
E_ERROR, out of memory) and when a fiber is destroyed while suspended. defered()(oner) is an accepted alias with identical behavior.- Native AOP advises the original bean methods (no proxies): a
stopExecution()value must match the declared return type exactly,staticmethods cannot carry advice, and an explicitparent::call to an advised method runs its advice. - Loading the extension disables PHP’s JIT compiler automatically (the engine does this for any executor override); OPcache itself keeps working. There is no flag to override this — size the performance expectations accordingly.
- Do not load Xdebug alongside
winter_bootin Swoole server environments. Any executor override (proven with a 20-line passthrough extension, so this is not specific towinter_boot) segfaults Swoole workers when Xdebug’s develop-mode exception hook formats a thrown exception. Either remove the Xdebug ini or setxdebug.mode=off. The runtime Docker image ships without Xdebug, so deployments are unaffected.
APCu (optional, ApcCache only)
Section titled “APCu (optional, ApcCache only)”ApcCache::isEnabled()returnsfalseunless the extension is both loaded and enabled. Callers must check it first: thecache()path calls the APCu functions directly, so skipping the check without APCu fails instead of degrading.- APCu is commonly disabled under CLI (
apc.enable_cli), soisEnabled()can befalsein console and migration runs even when web workers cache fine. Do not assume CLI and Swoole workers see the same cache state.
OpenTelemetry (optional, telemetry module)
Section titled “OpenTelemetry (optional, telemetry module)”- Enabling
OpenTelemetryModulewithout the extension fails fast: module startup throwsMissingExtensionException. - The extension alone is not enough — telemetry also needs the OpenTelemetry SDK, the SPI plugin bridge, and an
opentelemetry.yamlconfig wired through the module entry. When spans go missing, check exporter endpoint and sampler settings in that config next.
redis / memcache / rdkafka (only with their modules)
Section titled “redis / memcache / rdkafka (only with their modules)”These matter only when the corresponding module or backend is enabled; the core framework never requires them.
- redis (phpredis): needed for the Redis module (
PhpRedisTemplate, cluster template),RedisCache, Redis-backed locks and the async Redis queue store. Bothredisandswooleback the async paths. - memcache / memcached: needed for the Memcache module templates. The two extensions are different client libraries — enable the one matching the configured template.
- rdkafka (plus Swoole): needed for the Kafka module (producers/consumers) and the Kafka-backed DTCE queue. Without both, Kafka consumers and workers cannot start.
The runtime Docker image preinstalls redis, rdkafka and swoole (with pcntl, curl, zip, PostgreSQL drivers); memcache(d) and opentelemetry are added only when the application needs them.