Skip to content

Experimental sessions

Type: boolean
Default: false

Added in: astro@5.1.0

Sessions are used to store user state between requests for on-demand rendered pages.

This experimental feature allows you to store and access items such as login status, shopping cart contents, or other user-specific data:

src/components/CartButton.astro
---
export const prerender = false; // Not needed with 'server' output
const cart = await Astro.session.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

Sessions rely on a configurable session driver to store data on the session object. A session cookie stores an identifying session ID.

The session object allows you to interact with the stored user state (e.g. add items to a shopping cart) and the session ID (e.g. delete the session ID cookie when logging out).

Enabling experimental sessions

Section titled Enabling experimental sessions

To enable sessions, set the experimental.session flag to true. Sessions only work on pages with on-demand rendering, so you need to install an adapter that supports on-demand rendering, and ensure that any pages that use sessions are set to prerender: false, or output is set to server in the Astro config.

astro.config.mjs
{
adapter: node({
mode: "standalone",
}),
experimental: {
session: true,
},
}

Sessions require a storage driver to store the session data. The Node and Netlify adapters automatically configure a default driver for you, but other adapters currently require you to specify a driver manually. You can use any supported driver from unstorage.

If you are using an adapter that doesn’t have a default driver, or if you want to choose a different driver, you can configure it using the session configuration option:

astro.config.mjs
{
adapter: vercel(),
session: {
driver: "upstash",
},
experimental: {
session: true,
},
}

Configure session.driver with the unstorage driver name that corresponds to the storage feature provided by your hosting platform, such as the Cloudflare KV driver or the Deno KV driver. You can also use a cross-platform driver such as Upstash or Redis.

You can also pass any available options to the unstorage driver in a separate session.options object. See your chosen driver’s documentation for available options.

The following example sets a base prefix ("sessions") to use for all keys in Upstash:

astro.config.mjs
{
adapter: vercel(),
session: {
driver: "upstash",
options: {
base: "sessions",
},
},
experimental: {
session: true,
},
}

You can configure additional options for sessions in the session object.

Type: string | object
Default: astro-session

Configures the session cookie. This cookie is set in the response when a session is generated. No actual user data is stored in the cookie – just an ID that is used to identify a user’s session. The session.cookie option can be used to set options for this cookie. You can either provide a string, which will be used as the cookie name, or an object which allows additional options:

astro.config.mjs
{
session: {
// If set to a string, this will be used as the cookie name
// cookie: "my-session-id",
// If set to an object, this will allow advanced options to be set
cookie: {
name: "my-session-id"
sameSite: "Strict",
},
}
}

Type: number
Default: undefined

An optional default time-to-live expiration period for session values, in seconds.

By default, session values persist until they are deleted or the session is destroyed, and do not automatically expire because a particular amount of time has passed. Set session.ttl to add a default expiration period for your session values. Passing a ttl option to session.set() will override the global default for that individual entry.

astro.config.mjs
{
session: {
ttl: 60 * 60, // 1 hour
}
}

Once you have configured a driver, you can use the session object to interact with the session. The object is accessible as Astro.session in your Astro components and pages and on the context object in API endpoints, middleware and actions. The API is the same in all cases.

The session is generated automatically when it is first used and can be regenerated at any time with Astro.session.regenerate() or destroyed with Astro.session.destroy().

In most cases, you will only need to use Astro.session.get() and Astro.session.set(). For other available methods, see the API section.

In .astro components and pages, you can access the session object via the global Astro object. For example, to display the number of items in a shopping cart:

src/components/CartButton.astro
---
export const prerender = false; // Not needed with 'server' output
const cart = await Astro.session.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

In API endpoints, the session object is available on the context object. For example, to add an item to a shopping cart:

src/pages/api/addToCart.ts
import type { APIContext } from 'astro';
export async function POST(req: Request, context: APIContext) {
const cart = await context.session.get('cart');
cart.push(req.body.item);
await context.session.set('cart', cart);
return Response.json(cart);
}

In actions, the session object is available on the context object. For example, to add an item to a shopping cart:

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;
},
}),
};

In middleware, the session object is available on the context object. For example, to set the last visit time in the session:

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => {
context.session.set('lastVisit', new Date());
return next();
});

Sessions are automatically created when they are first accessed. The session object is available in all Astro contexts, including components, actions, and API endpoints. In components, it is accessed via the global Astro object, and in actions and API endpoints, it is available on the context object. The API is the same in all cases.

Values are serialized and deserialized using devalue, which is the same library used in content collections and actions. This means that supported types are the same, and include strings, numbers, Date, Map, Set, URL, arrays, and plain objects.

Type: (key: string) => Promise<any>

Returns the value of the given key in the session. If the key does not exist, it returns undefined.

Type: (key: string, value: any, options?: { ttl: number }) => void

Sets the value of the given key in the session. The value can be any serializable type. This method is synchronous and the value is immediately available for retrieval, but it is not saved to the backend until the end of the request.

Type: () => void

Regenerates the session ID. Best practice is to call this when a user logs in or escalates their privileges, to prevent session fixation attacks.

Type: () => void

Destroys the session, deleting the cookie and the object from the backend. This should be called when a user logs out or their session is otherwise invalidated.

For full details and to give feedback on this experimental API, see the Sessions RFC.

Contribute Community Sponsor