dFlow Logo
cookies cover picture

What Are Cookies? Best Practices and a Deep Dive

Avatar
Pavan Bhaskar
10 Jan, 2026
webdevNode.jsNextjs

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'
2
3const cookieStore = await cookies()
4
5cookieStore.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=None and Secure=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-domains
7 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.com from 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=None requires Secure=true
  • Secure=true may not work on http://localhost in all browsers (Safari especially)
1// Recommended configuration for local
2cookieStore.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=Lax is more permissive and works well locally
  • Secure=false allows cookies over http://localhost
  • Production still uses the safest possible configuration