Sessions and cookies solve the same problem (remembering a visitor) in different places. Here is how they compare.
| Cookie | Session | |
|---|---|---|
| Data stored | In the visitor’s browser | On the server |
| Visitor can read it | Yes | No (only the ID cookie) |
| Visitor can change it | Yes | No |
| Size | About 4 KB | Practically any size |
| Lifetime | You choose (minutes to years) | Until timeout or logout |
| Sent with every request | Yes, the whole value | Only the small ID |
| Good for | Preferences, remember-me tokens | Login state, cart, private data |
The relationship
A session uses a cookie. The only thing in the cookie is the session ID. The rest of the data stays on the server. So “sessions or cookies” is really “data on the server or data in the browser”.
Use a cookie when
- The data is harmless and the visitor may even change it: theme, language, “I closed the banner”.
- The data must survive a long time, even after the session is gone.
- The server should not need to keep anything.
Use a session when
- The data is private or must be trusted: who is logged in, what is in the cart.
- You need to store more than a few bytes.
- You want to be able to end it from the server (logout, ban).
Example: choose the right one
<?php
$cases = [
"Dark mode preference" => "cookie",
"The logged-in user's ID" => "session",
"Items in the shopping cart" => "session",
"Language the visitor picked" => "cookie",
"A CSRF token" => "session",
];
foreach ($cases as $thing => $where) {
echo str_pad($thing, 30) . $where . "\n";
}
Dark mode preference cookie
The logged-in user's ID session
Items in the shopping cart session
Language the visitor picked cookie
A CSRF token session
Both together: remember me
A “stay logged in” feature uses both. The session ends when the browser closes. A separate long-lived cookie holds a random token. When the session is gone, the server checks the token against the database and starts a new session. Remember Me shows how to do it safely.
Alternatives
- Tokens (JWT or opaque tokens) are common for APIs, where there is no browser session.
- Local storage in JavaScript stores data in the browser only. The server never sees it unless your code sends it.