> ## Documentation index
> Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
> Ask it with GET https://upstash.com/docs/ask?q=<keywords or question>. Short keywords rank best.
> Use these to discover all available pages before exploring further.
> Feature requests: https://upstash.com/docs/common/help/feature-requests.md lists what users asked for and how to vote for a request or add one.
> Page rating: `GET https://upstash.com/docs/feedback?path=/docs/redis/tutorials/express_session&helpful=true` (or `false`) records whether this page helped. An optional `comment` (URL-encoded, at most 500 characters) says what was missing or wrong. It is anonymous and needs no key. Comments hold no code, secrets or personal data.

# Express Session with Upstash Redis

> Store Express sessions in Upstash Redis with express-session, connect-redis and node-redis, so sessions survive restarts and work across multiple servers.

`express-session` keeps sessions in memory by default. That memory store loses
every session when the process restarts, and each server instance has its own
copy, so it does not work behind a load balancer. Storing sessions in Redis
fixes both.

The session store is [connect-redis](https://github.com/tj/connect-redis) with
the [node-redis](https://github.com/redis/node-redis) client.

### Step 1: Create a database

Create a Redis database as described in [Getting Started](../overall/getstarted).
On the database page, open the **Connect** section, select the **TCP** tab and
copy the connection string:

```text
rediss://default:YOUR_TOKEN@YOUR_ENDPOINT:6379
```

### Step 2: Create the project

```shell
mkdir express-session-redis && cd express-session-redis
npm init -y
npm install express express-session connect-redis redis
npm pkg set scripts.start="node index.js"
```

### Step 3: index.js

```javascript index.js
const express = require("express");
const session = require("express-session");
const { RedisStore } = require("connect-redis");
const { createClient } = require("redis");

const redisClient = createClient({ url: process.env.REDIS_URL });
redisClient.on("error", (err) => console.error("Redis error", err));
redisClient.connect().catch(console.error);

const app = express();

app.use(
  session({
    store: new RedisStore({ client: redisClient, prefix: "myapp:" }),
    secret: process.env.SESSION_SECRET || "replace-with-a-long-random-string",
    resave: false,
    saveUninitialized: false,
  })
);

app.get("/:page", (req, res) => {
  const views = req.session.views || {};
  const key = `page:${req.params.page}`;
  views[key] = (views[key] || 0) + 1;
  req.session.views = views;
  res.type("text").send(`You viewed /${req.params.page} ${views[key]} times`);
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
```

Each session is stored as one key with the `myapp:` prefix. connect-redis sets
a TTL (time to live) on the key from the session cookie's expiry, or one day
by default, so Redis deletes old sessions on its own.

### Step 4: Run the app

Put the connection string in a `.env` file and start the server:

```shell .env
REDIS_URL="rediss://default:YOUR_TOKEN@YOUR_ENDPOINT:6379"
SESSION_SECRET="a-long-random-string"
```

```shell
node --env-file=.env index.js
```

### Step 5: Check your work

Open http://localhost:3000/foo and http://localhost:3000/bar in two different
browsers and refresh a few times. Each browser has its own count:

```text
You viewed /foo 1 times
You viewed /foo 2 times
You viewed /bar 1 times
```

Restart the server and refresh again. The counts continue, because the sessions
are in Redis.

### Deploy

Set `REDIS_URL` and `SESSION_SECRET` as environment variables on your host.
See [Render](/redis/quickstarts/render), [Fly.io](/redis/quickstarts/fly) or
[DigitalOcean](/redis/quickstarts/digitalocean) for host-specific steps.

### FAQ

**How do I configure the session cookie?**

See the [express-session options](https://github.com/expressjs/session#options).
For production behind HTTPS, set `cookie: { secure: true }` and
`app.set("trust proxy", 1)` if a proxy terminates TLS.
