Skip to main content
Winter Boot’s asynchronous execution model lets you fire off any service or component method as a background task — the calling code returns immediately while a dedicated pool of Swoole worker processes handles the actual work. This non-blocking design keeps web request latency low even when individual operations are expensive, because heavy lifting happens outside the request/response cycle entirely. Under the hood, arguments are serialised into an in-memory (or Redis-backed) queue and consumed by background workers, so the concurrency model is process-based rather than thread-based.
For distributed task processing across multiple nodes with persistent queues, see the DTCE module. For event-driven consumers backed by Kafka or SQS, see Kafka and SQS.

Prerequisites

Async support is powered by the Swoole PHP extension. Install it via PECL and enable it in your php.ini before proceeding.
1

Install the Swoole extension

2

Enable Swoole in php.ini

Enable Async on Your Application Class

Add the #[EnableAsync] attribute to your #[WinterBootApplication] class. The framework validates at boot time that both attributes are present and that Swoole is loaded — a TypeError or AnnotationException is thrown otherwise.
MyApplication.php

Mark a Method as Async

Annotate any public, non-final, non-abstract method on a #[Service] or #[Component] bean with #[Async]. When the method is called at runtime the framework serialises its arguments and dispatches the call to a background worker — the caller receives control back instantly.
NotificationService.php
#[Async] only works on methods belonging to service or component beans managed by the Winter Boot container. Calling it on a plain PHP class instantiated with new will not run asynchronously — the method executes synchronously as a normal call.

Return Values

An #[Async] method must declare a void return type. Because the caller does not wait for the worker to finish, there is no mechanism to return a value back to the calling code.

Method Parameter Constraints

The framework serialises method arguments to pass them to a worker process. Each parameter must be typed as a scalar (int, float, string, or bool). Avoid mixed types; the framework logs an error at boot if it encounters them.
ReportService.php

Configuration

Configure the async worker pool in application.yml under winter.task.async:
application.yml
int
Total number of dedicated background worker processes to start.
int
Maximum number of async calls that can be queued and awaiting execution at any one time.
int
Upper limit in bytes for the combined serialised arguments of a single async call.

Queue Storage

By default, Winter Boot uses shared memory as its async queue. Pending calls are lost if the application restarts. For persistence across restarts, switch to the Redis-backed queue store provided by the winter-data-redis module:
application.yml
The Redis queue store requires the winter-data-redis module and a configured Redis connection. With it enabled, queued calls survive application restarts.

Complete Example

The following three files show a full fire-and-forget audit logging flow: the application class, the async service, and the controller that triggers it.
Use async logging, email dispatch, and audit trails as your first candidates for #[Async]. These are high-frequency, latency-sensitive operations that have no return value and are natural fits for fire-and-forget execution.