Description
With the rise of persistent memory runtimes like FrankenPHP, ensuring that services are strictly stateless has become a priority. While FPM hides state-related issues by killing the process after each request, Worker mode exposes them, leading to memory leaks or data contamination between requests.
While auditing a project for FrankenPHP compatibility using Igor-PHP (a static analysis tool I'm developing), the tool identified several state-related issues within the API Platform core (vendor folder). After verifying these findings on the main branch, I've confirmed that several core services are not yet fully stateless or lack memory reset mechanisms.
Identified Patterns & Examples
1. Static State Persistence
Properties using the static scope persist across the entire process lifetime. In Worker mode, these are overwritten on every request but stay in memory, which is inefficient and bypasses service-oriented architecture benefits.
- Example:
EntrypointAction
- Current code:
private static ?ResourceNameCollection $resourceNameCollection = null;
- Risk: Unnecessary global state persistence.
2. Unbounded Memory Growth (Missing ResetInterface)
Several singleton services maintain internal caches (as arrays) that grow with each unique input. Without a mechanism to clear them, these services cause slow memory leaks in long-running processes.
- Examples:
ResourceClassResolver, YamlPropertyExtractor.
- Impact: RAM usage will grow linearly over time until the worker is restarted.
3. State Contamination
Some services mutate internal properties during a request cycle. If an error or a specific edge case occurs, the property might keep its value for the next request, leading to unpredictable behavior.
- Example:
ErrorListener (mutation of $this->controller).
- Impact: Request B might inherit the "error state" or decision logic of Request A.
Proven track record
I have already applied a similar audit to the Symfony core, leading to improvements regarding state management in worker mode (see symfony/symfony#63964). My goal is to bring the same level of robustness to API Platform.
Proposed Solution
I suggest a series of PRs to:
- Refactor static properties into instance properties (since services are already singletons).
- Implement
ResetInterface on services holding internal caches so Symfony can automatically clear them between requests.
- Ensure methods are stateless by moving temporary state into local variables or method arguments.
I've already started working on these fixes. I'm aware of related issues like #7868, but this audit focuses specifically on service state and memory stability.
Are you open to receiving PRs for these improvements on the main branch?
Description
With the rise of persistent memory runtimes like FrankenPHP, ensuring that services are strictly stateless has become a priority. While FPM hides state-related issues by killing the process after each request, Worker mode exposes them, leading to memory leaks or data contamination between requests.
While auditing a project for FrankenPHP compatibility using Igor-PHP (a static analysis tool I'm developing), the tool identified several state-related issues within the API Platform core (vendor folder). After verifying these findings on the
mainbranch, I've confirmed that several core services are not yet fully stateless or lack memory reset mechanisms.Identified Patterns & Examples
1. Static State Persistence
Properties using the
staticscope persist across the entire process lifetime. In Worker mode, these are overwritten on every request but stay in memory, which is inefficient and bypasses service-oriented architecture benefits.EntrypointActionprivate static ?ResourceNameCollection $resourceNameCollection = null;2. Unbounded Memory Growth (Missing ResetInterface)
Several singleton services maintain internal caches (as arrays) that grow with each unique input. Without a mechanism to clear them, these services cause slow memory leaks in long-running processes.
ResourceClassResolver,YamlPropertyExtractor.3. State Contamination
Some services mutate internal properties during a request cycle. If an error or a specific edge case occurs, the property might keep its value for the next request, leading to unpredictable behavior.
ErrorListener(mutation of$this->controller).Proven track record
I have already applied a similar audit to the Symfony core, leading to improvements regarding state management in worker mode (see symfony/symfony#63964). My goal is to bring the same level of robustness to API Platform.
Proposed Solution
I suggest a series of PRs to:
ResetInterfaceon services holding internal caches so Symfony can automatically clear them between requests.I've already started working on these fixes. I'm aware of related issues like #7868, but this audit focuses specifically on service state and memory stability.
Are you open to receiving PRs for these improvements on the
mainbranch?