Sessions
Sessions let you remember things about a visitor across requests: who they are, what is in their cart, a one-time status message. Fast's session layer is built for the multi-worker event loop, and it gives you two drivers behind a single, simple API.
Enabling sessions
Sessions need a secret key. Generate one once, store it somewhere safe, and reuse it forever:
use Fast\Session\SessionConfig;
use_session(new SessionConfig(key: SessionConfig::generateKey()));
In a real app you would load that key from configuration rather than generating it inline, because a fresh key on every boot would invalidate every existing session:
use_session(new SessionConfig(
key: env_string('APP_KEY'),
secure: !env_bool('LOCAL_HTTP'),
));
The secure flag controls whether the cookie is marked Secure (HTTPS-only). Leave it on in production; turn it off only for local HTTP development.
Reading and writing
Inside a handler, session() gives you the current session:
get('/', function (): array {
session()->put('n', session()->get('n', 0) + 1);
return ['visits' => session()->get('n')];
});
The full set of operations is small and familiar:
session()->put('locale', 'en');
$locale = session()->get('locale', 'en'); // with a default
session()->has('cart');
session()->forget('cart');
$value = session()->pull('one-time'); // get and remove in one step
session()->all();
session()->flush(); // clear everything
session()->regenerate(); // new id, keep the data
session()->invalidate(); // new id, drop the data
Flash messages
Flash data lives for exactly one request: the next one. It is perfect for the "Saved!" banner you show after a redirect:
post('/profile', function (): Fast\Http\Response {
// ... save the profile ...
flash('status', 'Profile saved.');
return redirect('/profile');
});
get('/profile', fn (): string => render('profile', [
'status' => session()->get('status'), // present once, then gone
]));
Two drivers, one API
Fast ships two session drivers. You choose with the driver option, and your code does not change either way:
| Driver | How it works | Best for |
|---|---|---|
| cookie (default) | The whole session is stored in an encrypted, authenticated cookie. No server state at all. | Flash, CSRF, auth identity, small data. |
| store | The cookie holds only an encrypted id; the data lives in a master-forked, sharded in-memory store shared across workers. | Larger sessions, server-side revocation. |
The cookie driver is stateless and scales linearly across every worker and core, because there is no shared server state to coordinate. The store driver trades that for the ability to hold more data and revoke sessions server-side:
use_session(new SessionConfig(
key: SessionConfig::generateKey(),
driver: 'store',
shardCount: 4,
));
Efficiency and security notes
A nice detail: the cookie is only rewritten when the session actually changes. A request that reads the session but does not modify it emits no Set-Cookie and does no store I/O at all.
Cookies are encrypted and authenticated with libsodium, so tampering is detected and a bad cookie is simply treated as a fresh session. They default to
HttpOnly,SameSite=Lax, andSecure. The cookie driver caps out around 4 KB and cannot revoke a session before it expires; the store driver is in-memory and non-durable, so a shard restart drops its sessions. Pick the trade-off that fits.
Sessions also underpin two closely related features. Next up is CSRF Protection.