Getting started with the Sessions API in Astro
Learn how to use Astro's new Sessions API to manage server-side state like shopping carts and user data, without relying on cookies or client-side JavaScript.
Managing per-user state in a web app can be challenging, especially when you want to keep things fast, secure, and server-rendered. Astro’s Sessions API offers a straightforward way to handle things like logged-in users, carts, or temporary form state. It avoids the complexity of cookies and client-side workarounds by keeping everything on the server.
What are sessions in Astro?
Sessions in Astro offer a secure, scalable way to store data between requests without relying on cookies or client-side storage. This feature is especially useful for things like:
- Shopping carts
- Authenticated user sessions
- Form state
- Visit tracking
Unlike cookies, session data is stored on the server. This means there’s no size limit, no need for encryption, and no risk of tampering from the client.
When should you use sessions?
Use Astro Sessions when you need to:
- Share state across pages without relying on query params or localStorage.
- Store sensitive or bulky data you don’t want exposed in the client.
- Avoid shipping unnecessary client-side JavaScript for dynamic behavior.
How sessions work in Astro
The Astro.session
object is available globally in server-rendered .astro
components and pages. In server endpoints, actions, and middleware, it’s available as context.session
.
Basic example: shopping cart button
---
export const prerender = false;
const cart = await Astro.session?.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>
This component fetches the user’s cart from the session and displays the number of items, without any JavaScript sent to the client.
Setting up sessions
Most adapters like Node, Netlify, and Cloudflare come with a default session driver pre-configured.
For others like Vercel, you’ll need to specify a storage driver:
// astro.config.mjs
import vercel from "@astrojs/vercel/serverless";
export default {
adapter: vercel(),
session: {
driver: 'redis',
},
};
See the Astro adapter docs for info on supported drivers.
Working with session data
Astro’s Sessions API gives you five key methods:
get(key)
- Fetch a valueset(key, value)
- Store a valuedestroy()
- Delete the session entirelyregenerate()
- Create a new session IDid
- Access the current session ID
Example: API route
// src/pages/api/addToCart.ts
export async function POST(context) {
const cart = await context.session?.get('cart') || [];
const data = await context.request.json();
if (!data?.item) {
return new Response('Item is required', { status: 400 });
}
cart.push(data.item);
await context.session?.set('cart', cart);
return Response.json(cart);
}
Example: server actions
// src/actions/addToCart.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
export const server = {
addToCart: defineAction({
input: z.object({ productId: z.string() }),
handler: async (input, context) => {
const cart = await context.session?.get('cart') || [];
cart.push(input.productId);
await context.session?.set('cart', cart);
return cart;
},
}),
};
Using sessions in middleware
You can read and write session data during a request using Astro middleware:
// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => {
context.session?.set('lastVisit', new Date());
return next();
});
Note: Sessions are not currently supported in edge middleware.
Adding type safety (optional but recommended)
You can define types for your session data using App.SessionData
:
// src/env.d.ts
declare namespace App {
interface SessionData {
user: {
id: string;
name: string;
};
cart: string[];
}
}
This enables type-checking and auto-complete in your editor, helping you catch bugs early.
Performance benefits of server-side sessions
Using Astro’s server-side sessions provides several important advantages over traditional cookie-based or client-side state management:
Faster page loads
Session data stays on the server, so you don’t need to serialize and send bulky state back and forth on every request. That means smaller payloads and faster pages, especially important for mobile users and low-bandwidth connections.
Improved security
Unlike cookies or localStorage
, session data isn’t exposed to the client. That makes it immune to tampering, accidental leaks, or XSS attacks. Sensitive information like user IDs, roles, or in-progress form data stays safely on the server.
Centralized state management
With sessions, state is always accurate and available across routes and requests, regardless of the client’s environment. There’s no need to rehydrate state from the browser, making your code simpler and easier to maintain.
Use only what you need
Because session values are requested explicitly (for example, get('cart')
), you’re not bloating every response with unnecessary data like you might with cookies. It’s efficient by design.
Common pitfalls and how to avoid them
Even though Astro Sessions are simple to use, there are a few common mistakes that can trip up developers. Here’s what to watch out for:
Sessions don’t work in static builds
Sessions require server-side rendering to function. If you’re using export const prerender = true
or have static output configured, session data won’t be available.
Fix: Set prerender = false
in any component or page that uses session data.
---
export const prerender = false;
---
Missing session driver for some adapters
Not all adapters (like Vercel) have a session driver configured out of the box.
Fix: Be sure to define a session.driver
in your astro.config.mjs
:
session: {
driver: 'redis',
},
Trying to store unsupported data types
Session values are serialized using devalue
, which means functions, class instances, or complex types like Promise
or Symbol
can’t be stored.
Fix: Stick to serializable types like strings, numbers, arrays, plain objects, Date
, Map
, and Set
.
Forgetting to await session methods
Since methods like get()
and set()
are async, forgetting await
can lead to subtle bugs.
Fix: Always await
session method calls:
const cart = await context.session?.get('cart');
Final thoughts
Astro’s Sessions API introduces powerful new patterns for building dynamic, server-first web apps while keeping your frontend fast and JavaScript-free.
Whether you’re building a simple form or a complex ecommerce experience, sessions provide a secure and elegant way to manage state on the server.
Further reading
Ready to try it? Install Astro 5.7 and start managing state efficiently using server-side sessions.