In Laravel 13, what does SESSION_DRIVER default to, and how do the database, file, cookie, redis and array drivers differ?
answer
- skeleton default is database
- sessions table ships in the users migration
- make:session-table if it is missing
- cookie driver: whole payload client-side
- array: never persisted, for tests
basics
~20 sLaravel 13's skeleton sets SESSION_DRIVER=database, storing sessions in a sessions table that its first migration creates. file suits one server, cookie keeps the whole payload in an encrypted cookie, redis and memcached are shared fast stores, and array persists nothing.
solid answer
~40 sIn Laravel 13 the skeleton's `.env.example` and `config/session.php` both default `SESSION_DRIVER` to `database`, and the `sessions` table (id, user_id, ip_address, user_agent, payload, last_activity) is created by the skeleton's `0001_01_01_000000_create_users_table` migration; `php artisan make:session-table` generates it if missing. `file` writes to `storage/framework/sessions`, fine for one server. `cookie` stores the entire encrypted session in the browser, so it is stateless on the server but size-limited and cannot use session blocking. `redis` and `memcached` are fast shared stores with TTL expiry; `SESSION_CONNECTION` picks the Redis connection. `array` keeps data in memory for one request, which suits tests. The `database` and `file` drivers are cleaned by a lottery, `[2, 100]` by default.
code
bash · 3 lines# generate the sessions table migration when it is missing
php artisan make:session-table
php artisan migratego deeper
Know that SESSION_DRIVER picks the storage, that a new Laravel 13 app uses the database, and that tests use the array driver.
Compare the drivers on sharing, expiry and size, and explain the sessions table, make:session-table and the garbage-collection lottery.
Pick a driver for multi-server deployments, isolate Redis sessions from cache flushes, and plan for the logout that any driver switch causes.
Weigh operational cost against capability, such as per-user session listing in the database versus the throughput of an in-memory store.
## Where the default comes from Laravel 13's application skeleton sets the session driver in two places: - `.env.example` contains `SESSION_DRIVER=database`, `SESSION_LIFETIME=120` and `SESSION_ENCRYPT=false`; - `config/session.php` reads `'driver' => env('SESSION_DRIVER', 'database')`. The skeleton's first migration, `0001_01_01_000000_create_users_table.php`, creates three tables: `users`, `password_reset_tokens` and **`sessions`**. So a new app on SQLite has working database sessions after its first `migrate`. If an app lacks the table, for example after changing drivers, `php artisan make:session-table` (alias `session:table`) generates the migration. Tutorials written for older skeletons often show `SESSION_DRIVER=file`; that is still a supported driver, just not the default any more. ## The drivers compared | Driver | Where data lives | Shared across servers | Expiry | Notes | |---|---|---|---|---| | `database` | `sessions` table | yes | lottery GC deletes rows by `last_activity` | records `user_id`, IP and user agent per session | | `file` | `storage/framework/sessions` | no, unless the disk is shared | lottery GC | simplest on a single server | | `cookie` | an encrypted cookie in the browser | yes (the client carries it) | cookie lifetime | size-limited; incompatible with session blocking | | `redis` | a Redis connection (`SESSION_CONNECTION`) | yes | cache TTL | fast; needs PhpRedis or predis | | `memcached` | Memcached | yes | cache TTL | fast; data can be evicted under memory pressure | | `array` | PHP memory | no | end of request | not persisted; used in tests | Other drivers, such as `dynamodb`, also exist. ## How each behaves in production - **database.** A write per request that touches the session, but no extra infrastructure. The `user_id` column lets an app list or revoke a user's other sessions, which the cache-based drivers cannot do cheaply. The `lottery` setting (`[2, 100]`, a 2% chance per request) triggers deletion of expired rows. - **file.** Each session is a file. Behind a load balancer without sticky sessions, the next request can land on a server that has never seen the file, and the user appears logged out. - **cookie.** Nothing is stored server-side; the payload is serialized, encrypted and sent back on every request. Browsers limit cookie size to roughly 4 KB, so a quote wizard that stores arrays can outgrow it. Because every request carries the whole payload, it also costs bandwidth. - **redis / memcached.** Built on the cache-based handler, whose garbage collection does nothing because the store expires keys by TTL. Put sessions on a Redis connection separate from the one you flush during deploys. - **array.** Used by `phpunit.xml` in the skeleton, which sets `SESSION_DRIVER=array` so tests do not touch real storage. ## Choosing for an insurance quote wizard 1. **Single server, simple hosting**: keep `database`; it survives restarts and needs nothing new. 2. **Several web servers**: `database` or `redis`, never `file` without shared storage. 3. **High traffic with Redis already present**: `redis`, with its own connection or database index. 4. **Stateless edge deployments**: `cookie` only if the payload is tiny and no route uses `->block()`. Switching drivers logs everyone out, because existing sessions live in the old store. ## Related settings in config/session.php - `lifetime` (minutes, default 120) and `expire_on_close`; - `encrypt` (default false) to encrypt payloads at rest; - `table` and `connection` for the database driver; - `store` for the cache store used by the cache-based drivers. ## A note on the payload itself Whatever the driver, the stored value is the same string: the session's attributes, serialized according to the `serialization` option and optionally encrypted when `encrypt` is true. That is why drivers are interchangeable in code, and why a driver switch cannot carry sessions over by itself: the new store simply holds no rows, files or keys for the existing session IDs.
- Why does the file session driver log users out at random behind a load balancer?Each session lives in a file under `storage/framework/sessions` on one server. Without sticky sessions or a shared disk, the next request may reach a server that has no such file, so Laravel starts an empty session and the user looks logged out. A shared store such as `database` or `redis` removes the problem.
- When do expired database sessions actually get deleted?On a lottery. `config/session.php` sets `'lottery' => [2, 100]`, so roughly 2 in 100 requests run the handler's garbage collection, which deletes rows whose `last_activity` is older than the lifetime. Cache-based drivers skip this, because the cache expires keys by TTL.
saying these in an interview costs you the question
- Laravel 13 stores sessions in files by default
- The file driver works fine behind any load balancer
- The cookie driver can hold any amount of session data
- The array driver persists sessions in memory between requests
- make:session-table is required in every new app