From 66cc00b9ac3ba8438a4f3647ac1c82fd03ea9c33 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 27 May 2026 07:57:47 +0000 Subject: [PATCH 1/6] Initial plan From 0e23978a0bfef72c67e9e3c87e19e027367a88fc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 27 May 2026 08:02:59 +0000 Subject: [PATCH 2/6] Add session/context/cart lifetime overview docs --- guides/hosting/performance/session.md | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/guides/hosting/performance/session.md b/guides/hosting/performance/session.md index 8ad4b9af4..92125f5b9 100644 --- a/guides/hosting/performance/session.md +++ b/guides/hosting/performance/session.md @@ -9,6 +9,36 @@ nav: Shopware, by default, uses the session storage configured in PHP. On most installations, this is the file system. In smaller setups, you will not need to take care of sessions. However, for larger setups using clustering or with a lot of traffic, you will probably configure alternative session storage, such as Redis, to reduce the load on the database. +## Session, context, and cart lifetime + +Shopware uses multiple lifecycles in parallel. A customer can still have a valid cart token while the Symfony session is already gone, or the other way around. + +```mermaid +sequenceDiagram + autonumber + participant Browser + participant Symfony Session + participant Sales Channel Context + participant Cart + + Browser->>Symfony Session: Store session cookie + Symfony Session->>Sales Channel Context: Resolve context token + Sales Channel Context->>Cart: Load cart by token + Note over Symfony Session: framework.session.cookie_lifetime
framework.session.gc_maxlifetime + Note over Sales Channel Context: shopware.api.store.context_lifetime
shopware.sales_channel_context.expire_days + Note over Cart: shopware.cart.expire_days +``` + +| Scope | Key / token | Controlled by | What expires | +| --- | --- | --- | --- | +| Browser session cookie | Symfony session cookie | `framework.session.cookie_lifetime` | How long the browser keeps the cookie | +| Server-side session data | Symfony session storage entry | `framework.session.gc_maxlifetime` | When session data can be garbage collected | +| Store API context token | Sales channel context token | `shopware.api.store.context_lifetime` | Store API context token validity | +| Persisted sales channel context | Sales channel context record | `shopware.sales_channel_context.expire_days` | Stored context data in Shopware | +| Cart persistence | Cart token and cart data | `shopware.cart.expire_days` | Persisted cart data | + +Longer lifetimes improve convenience, but they increase risk on shared devices because user-related data remains available for a longer time. They can also increase infrastructure usage, for example Redis memory consumption, because session and context data stay in storage longer. + ## Session adapters ### Configure Redis using PHP.ini From e2e6a38fa7fb41ae4cea7f72863ec78cf0bc31ff Mon Sep 17 00:00:00 2001 From: Micha Date: Fri, 29 May 2026 11:17:35 +0200 Subject: [PATCH 3/6] change/ --- guides/hosting/performance/session.md | 38 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/guides/hosting/performance/session.md b/guides/hosting/performance/session.md index 92125f5b9..f3676fca4 100644 --- a/guides/hosting/performance/session.md +++ b/guides/hosting/performance/session.md @@ -11,31 +11,37 @@ Shopware, by default, uses the session storage configured in PHP. On most instal ## Session, context, and cart lifetime -Shopware uses multiple lifecycles in parallel. A customer can still have a valid cart token while the Symfony session is already gone, or the other way around. +Shopware runs several lifecycles in parallel. The Symfony session, the sales channel context, and the persisted cart each have their own lifetime, and each is controlled by a different configuration value. The diagram below shows how they are resolved on a request and which setting governs each step. ```mermaid sequenceDiagram autonumber - participant Browser - participant Symfony Session - participant Sales Channel Context - participant Cart - - Browser->>Symfony Session: Store session cookie - Symfony Session->>Sales Channel Context: Resolve context token - Sales Channel Context->>Cart: Load cart by token - Note over Symfony Session: framework.session.cookie_lifetime
framework.session.gc_maxlifetime - Note over Sales Channel Context: shopware.api.store.context_lifetime
shopware.sales_channel_context.expire_days - Note over Cart: shopware.cart.expire_days + participant B as Browser + participant S as Symfony session + participant SCC as Sales Channel Context + participant C as Cart + + B->>S: Request with session cookie + Note over B,S: framework.session.cookie_lifetime — browser keeps the cookie
framework.session.gc_maxlifetime — server keeps the session data + + S->>SCC: Resolve context via context token + Note over SCC: shopware.api.store.context_lifetime — token still accepted
shopware.sales_channel_context.expire_days — stored context cleanup + + SCC->>C: Load cart by context token + Note over C: shopware.cart.expire_days — persisted cart cleanup + + C-->>B: Cart and context restored (a new token is issued if the context expired) ``` -| Scope | Key / token | Controlled by | What expires | +Each hop in the diagram is governed by its own setting, so the lifecycles are independent: a customer can still have a valid cart token while the Symfony session is already gone, or keep a session cookie long after the persisted context has been cleaned up. + +| Scope | Key / token | Controlled by | What it limits | | --- | --- | --- | --- | | Browser session cookie | Symfony session cookie | `framework.session.cookie_lifetime` | How long the browser keeps the cookie | | Server-side session data | Symfony session storage entry | `framework.session.gc_maxlifetime` | When session data can be garbage collected | -| Store API context token | Sales channel context token | `shopware.api.store.context_lifetime` | Store API context token validity | -| Persisted sales channel context | Sales channel context record | `shopware.sales_channel_context.expire_days` | Stored context data in Shopware | -| Cart persistence | Cart token and cart data | `shopware.cart.expire_days` | Persisted cart data | +| Store API context token | Sales channel context token | `shopware.api.store.context_lifetime` | How long a context token stays valid before a new one is issued (`DateInterval`, e.g. `P1D`) | +| Persisted sales channel context | Sales channel context record | `shopware.sales_channel_context.expire_days` | When the cleanup task removes stored context records | +| Cart persistence | Cart token and cart data | `shopware.cart.expire_days` | When the cleanup task removes persisted carts | Longer lifetimes improve convenience, but they increase risk on shared devices because user-related data remains available for a longer time. They can also increase infrastructure usage, for example Redis memory consumption, because session and context data stay in storage longer. From d32af092eee893758cf9538fb5560be22bfb1a20 Mon Sep 17 00:00:00 2001 From: Micha Date: Fri, 29 May 2026 11:24:35 +0200 Subject: [PATCH 4/6] fix/mermaid --- guides/hosting/performance/session.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/hosting/performance/session.md b/guides/hosting/performance/session.md index f3676fca4..e4f27d30e 100644 --- a/guides/hosting/performance/session.md +++ b/guides/hosting/performance/session.md @@ -22,7 +22,7 @@ sequenceDiagram participant C as Cart B->>S: Request with session cookie - Note over B,S: framework.session.cookie_lifetime — browser keeps the cookie
framework.session.gc_maxlifetime — server keeps the session data + Note over S: framework.session.cookie_lifetime — browser keeps the cookie
framework.session.gc_maxlifetime — server keeps the session data S->>SCC: Resolve context via context token Note over SCC: shopware.api.store.context_lifetime — token still accepted
shopware.sales_channel_context.expire_days — stored context cleanup From 6736f8994b3ca3a34b0a3bb6f8654814c2ec0e14 Mon Sep 17 00:00:00 2001 From: Micha Hobert Date: Fri, 29 May 2026 11:26:16 +0200 Subject: [PATCH 5/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- guides/hosting/performance/session.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/hosting/performance/session.md b/guides/hosting/performance/session.md index e4f27d30e..32183281a 100644 --- a/guides/hosting/performance/session.md +++ b/guides/hosting/performance/session.md @@ -33,7 +33,7 @@ sequenceDiagram C-->>B: Cart and context restored (a new token is issued if the context expired) ``` -Each hop in the diagram is governed by its own setting, so the lifecycles are independent: a customer can still have a valid cart token while the Symfony session is already gone, or keep a session cookie long after the persisted context has been cleaned up. +Each hop in the diagram is governed by its own setting, so the lifecycles are independent: a customer can still have a valid cart token while the Symfony session is already gone, or keep a session cookie long after the persisted context has been cleaned up. The following table compares the settings that control each lifecycle. | Scope | Key / token | Controlled by | What it limits | | --- | --- | --- | --- | From 0beeab28faebd2af4c7f51a49c43618872c44724 Mon Sep 17 00:00:00 2001 From: Micha Date: Fri, 29 May 2026 16:20:34 +0200 Subject: [PATCH 6/6] add/info-on-settings --- guides/hosting/performance/session.md | 59 +++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/guides/hosting/performance/session.md b/guides/hosting/performance/session.md index 32183281a..1e305818b 100644 --- a/guides/hosting/performance/session.md +++ b/guides/hosting/performance/session.md @@ -35,13 +35,58 @@ sequenceDiagram Each hop in the diagram is governed by its own setting, so the lifecycles are independent: a customer can still have a valid cart token while the Symfony session is already gone, or keep a session cookie long after the persisted context has been cleaned up. The following table compares the settings that control each lifecycle. -| Scope | Key / token | Controlled by | What it limits | -| --- | --- | --- | --- | -| Browser session cookie | Symfony session cookie | `framework.session.cookie_lifetime` | How long the browser keeps the cookie | -| Server-side session data | Symfony session storage entry | `framework.session.gc_maxlifetime` | When session data can be garbage collected | -| Store API context token | Sales channel context token | `shopware.api.store.context_lifetime` | How long a context token stays valid before a new one is issued (`DateInterval`, e.g. `P1D`) | -| Persisted sales channel context | Sales channel context record | `shopware.sales_channel_context.expire_days` | When the cleanup task removes stored context records | -| Cart persistence | Cart token and cart data | `shopware.cart.expire_days` | When the cleanup task removes persisted carts | +| Scope | Key / token | Controlled by | What it limits | +|---------------------------------|-------------------------------|----------------------------------------------|----------------------------------------------------------------------------------------------| +| Browser session cookie | Symfony session cookie | `framework.session.cookie_lifetime` | How long the browser keeps the cookie | +| Server-side session data | Symfony session storage entry | `framework.session.gc_maxlifetime` | When session data can be garbage collected | +| Store API context token | Sales channel context token | `shopware.api.store.context_lifetime` | How long a context token stays valid before a new one is issued (`DateInterval`, e.g. `P1D`) | +| Persisted sales channel context | Sales channel context record | `shopware.sales_channel_context.expire_days` | When the cleanup task removes stored context records | +| Cart persistence | Cart token and cart data | `shopware.cart.expire_days` | When the cleanup task removes persisted carts | + +::: info +**Symfony session: cookie vs. server data** + +`framework.session.cookie_lifetime` and `framework.session.gc_maxlifetime` control different sides of the same session: + +- **`cookie_lifetime`** - how long the **browser** keeps and sends the session cookie. If not set in Symfony, PHP's `session.cookie_lifetime` applies (typically `0`, meaning until the browser closes). +- **`gc_maxlifetime`** - how long the **server** keeps session data before it can be garbage-collected. If not set in Symfony, PHP's `session.gc_maxlifetime` applies (typically `1440` seconds / 24 minutes). + +These values can diverge. A customer may still send a session cookie while the server has already deleted the session data, which starts a new empty session on the next request. If you need predictable login duration, configure both values explicitly to similar lengths. + +The same pattern applies further down the stack: `shopware.api.store.context_lifetime` controls when a context token is still accepted, while `shopware.sales_channel_context.expire_days` and `shopware.cart.expire_days` control when cleanup tasks remove stored records. +::: + +### Configuration + +The Symfony session settings from the first two table rows belong in `config/packages/framework.yaml`. The Shopware-specific lifetimes belong in `config/packages/shopware.yaml`. Override only the values you need; unset keys keep the Symfony or Shopware defaults. + +Symfony session lifetimes (browser cookie and server-side session data): + +```yaml +# config/packages/framework.yaml +framework: + session: + cookie_lifetime: 86400 # seconds + gc_maxlifetime: 86400 # seconds +``` + +If you cannot change Symfony configuration, set the PHP ini values instead (`session.cookie_lifetime` and `session.gc_maxlifetime` in `php.ini`). + +Store API context token and cleanup lifetimes (context token, persisted context, and cart): + +```yaml +# config/packages/shopware.yaml +shopware: + api: + store: + context_lifetime: 'P1D' # DateInterval - token validity (default: 1 day) + sales_channel_context: + expire_days: 120 # days - cleanup of stored context records + cart: + expire_days: 120 # days - cleanup of persisted carts +``` + +`context_lifetime` uses [PHP DateInterval notation](https://www.php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters), for example `P1D` (1 day) or `P7D` (7 days). The `expire_days` values are used by scheduled cleanup tasks; see [Scheduled tasks](../infrastructure/scheduled-task.md). Longer lifetimes improve convenience, but they increase risk on shared devices because user-related data remains available for a longer time. They can also increase infrastructure usage, for example Redis memory consumption, because session and context data stay in storage longer.