Skip to main content
Winter Boot’s locking abstraction gives you declarative, AOP-based concurrency control over any public bean method. By annotating a method with #[Lockable] you guarantee that only one caller can execute that method at a time — either at the local-node level (default) or across an entire cluster when a distributed LockManager is provided. Parameter expressions such as name: "order-#{id}" allow the lock scope to be narrowed down to a specific resource instance, preventing unnecessary serialization of unrelated requests.

#[Lockable] Options

string
required
Unique name for the lock. Supports #{param} interpolation to bind method parameters into the lock name (e.g. "order-#{id}").
string
default:"Framework default"
Bean name of a class implementing LockManager. Omit to use local node locking.
int
default:"0"
How long (in milliseconds) to wait for the lock before failing. 0 means fail immediately if the lock is not available.
int
default:"0"
Maximum time (in seconds) the lock is held before it is automatically released. 0 means no TTL limit.

Local Node Locking

The framework provides local node locking out of the box — no extra configuration or bean is needed. Only one process on the same node can execute the annotated method at a time. The #{id} syntax binds the method parameter $id into the lock name, so two concurrent calls with different order IDs proceed in parallel while two calls for the same ID are serialized.
OrderService.php
Always set a ttlSeconds value in production. Without it, a crashed process can hold the lock indefinitely and block all subsequent callers.

Distributed Locking

For deployments with multiple nodes you need a LockManager backed by a shared store so that locks are visible across the entire cluster. Provide a bean that implements LockManager, pass its bean name to the lockManager option, and the #[Lockable] attribute works identically to local locking from your code’s perspective. Supported backends include Redis, database locks, Apache ZooKeeper, Consul, and anything else you can wrap in a LockManager implementation.
1

Annotate the method with a named lockManager

OrderService.php
2

Register the LockManager bean

LockConfig.php
The Symfony Lock component supports Redis, Memcached, PDO/DBAL databases, ZooKeeper, Consul, and more — all of which can be adapted to the Winter Boot LockManager interface.

Handling LockException

If the lock cannot be acquired within waitMilliSecs milliseconds, Winter Boot throws a LockException. Catch it in your controller or service layer and return an appropriate response to the caller.
OrderController.php