
What Are Cookies? Best Practices and a Deep Dive

Cookies are small pieces of data (key–value pairs) that a web server sends to a user’s browser. The browser stores these cookies and automatically sends them back to the server on subsequent requests, allowing the server to remember state and deliver a personalized experience.
Common Use Cases
1. Session Management
When you log in to a website, the server typically stores an authentication token (often a JWT) in a cookie. On every subsequent request, the browser sends this cookie back so the server can verify the user’s identity without asking them to log in again.
2. Personalization
Cookies are commonly used to store user preferences such as:
- Language
- Theme (dark/light mode)
- Region or locale
This allows the application to preserve preferences across page reloads and browser tabs.
3. Other Use Cases
- Analytics and tracking
- Shopping carts
- Feature flags
- A/B testing
Cookie Security Best Practices
HttpOnly
- Prevents JavaScript from accessing the cookie via
document.cookie - Protects sensitive cookies from being stolen during XSS attacks
- Should always be enabled for authentication/session cookies
Even if an attacker injects JavaScript into your site, they cannot read HttpOnly cookies.
Secure
- Ensures cookies are only sent over HTTPS
- Prevents cookies from being transmitted over unencrypted HTTP connections
- Essential for protecting cookies on public or insecure networks
Example (Nextjs)
1import { cookies } from 'next/headers'23const cookieStore = await cookies()45cookieStore.set({6 name: 'my-cookie',7 value: 'secret-value',8 expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7),9 httpOnly: true,10 secure: true,11})
Advanced: Sharing Cookies Across Domains
Cookies can be shared between a root domain and its subdomains when configured correctly. This is useful when you have setups like:
mydomain.com(marketing site)app.mydomain.com(application)
Root → Subdomains (Top → Bottom)
To make a cookie set on mydomain.com available to all subdomains (*.mydomain.com):
- Set the cookie domain to
mydomain.com - Use
SameSite=NoneandSecure=true
1cookieStore.set({2 name: 'my-cookie',3 value: 'secret-value',4 domain: 'mydomain.com',5 expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7),6 sameSite: 'none', // This allows cookie available on sub-domains7 httpOnly: true,8 secure: true,9})
Subdomain → Root (Bottom → Top)
By default, cookies set on a subdomain (e.g. app.mydomain.com) are not accessible on the root domain.
To make a cookie accessible to both:
- Explicitly set the cookie domain to
.mydomain.comfrom the subdomain
1cookieStore.set({2 name: 'my-cookie',3 value: 'secret-value',4 domain: '.mydomain.com',5 expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7),6 sameSite: 'none',7 httpOnly: true,8 secure: true,9})
This allows both mydomain.com and app.mydomain.com to receive the cookie.
Cookie Deletion Caveat (Next.js)
In Next.js, calling:
1cookieStore.delete('my-cookie')
may fail if the cookie was originally set with a custom domain.
To reliably delete a cookie:
- Re-set the cookie with the same
domain - Set the expiration date to the past
1cookieStore.set({2 name: 'my-cookie',3 value: '',4 domain: '.mydomain.com',5 expires: new Date(0),6})
Local Development Setup
During local development, browsers handle cookies differently:
SameSite=NonerequiresSecure=trueSecure=truemay not work onhttp://localhostin all browsers (Safari especially)
1// Recommended configuration for local2cookieStore.set({3 name: 'my-cookie',4 value: 'secret-value',5 httpOnly: true,6 sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax',7 secure: process.env.NODE_ENV === 'production',8})
SameSite=Laxis more permissive and works well locallySecure=falseallows cookies overhttp://localhost- Production still uses the safest possible configuration