Skip to main content
This guide demonstrates how to use Upstash Redis in AWS Lambda functions. The HTTP-based connection makes it perfect for serverless environments where traditional TCP connections are problematic.

Why Upstash Redis for Lambda?

  • Connectionless: HTTP-based, no connection pooling needed
  • Fast cold starts: No connection overhead
  • Pay-per-request: Aligned with Lambda’s pricing model
  • Global: Low latency from any AWS region

Prerequisites

1

Create AWS Account

Sign up for an AWS account if you don’t have one
2

Install AWS CLI

Set up and configure AWS CLI with your credentials
3

Create Upstash Redis Database

Create a Redis database using Upstash Console or Upstash CLI

Quick Start

Project Setup

1

Create Project Directory

mkdir my-lambda-function
cd my-lambda-function
2

Initialize npm and Install Dependencies

npm init -y
npm install @upstash/redis
3

Create Lambda Function

Create index.js with your Lambda handler code

Example: Counter Function

This example implements a simple counter that increments on each Lambda invocation.
const { Redis } = require('@upstash/redis');

const redis = Redis.fromEnv();

exports.handler = async (event) => {
    const count = await redis.incr("counter");
    return {
        statusCode: 200,
        body: JSON.stringify('Counter: ' + count),
    };
};

Deployment

Create Deployment Package

1

Install Dependencies

npm install
2

Create ZIP Archive

zip -r my_deployment_package.zip .
This creates a ZIP file containing your code and node_modules.

Deploy with AWS CLI

aws lambda create-function --function-name counterFunction \
--runtime nodejs20.x --handler index.handler \
--role <YOUR_LAMBDA_EXECUTION_ROLE_ARN> \
--zip-file fileb://my_deployment_package.zip \
--region us-east-1 \
--environment "Variables={UPSTASH_REDIS_REST_URL=<YOUR_URL>,UPSTASH_REDIS_REST_TOKEN=<YOUR_TOKEN>}"
Replace <YOUR_LAMBDA_EXECUTION_ROLE_ARN> with your Lambda execution role ARN. This role must have basic Lambda execution permissions.

Get Your Upstash Credentials

From your Upstash Console:
  1. Select your Redis database
  2. Click on the REST API tab
  3. Copy the UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN

Advanced Examples

Session Storage

const { Redis } = require('@upstash/redis');

const redis = Redis.fromEnv();

exports.handler = async (event) => {
    const sessionId = event.headers['session-id'];
    
    if (!sessionId) {
        return {
            statusCode: 400,
            body: JSON.stringify({ error: 'Session ID required' })
        };
    }
    
    // Get or create session
    let session = await redis.get(`session:${sessionId}`);
    
    if (!session) {
        session = {
            id: sessionId,
            createdAt: Date.now(),
            visits: 0
        };
    }
    
    // Update session
    session.visits++;
    session.lastVisit = Date.now();
    
    // Store with 1 hour expiration
    await redis.set(`session:${sessionId}`, session, { ex: 3600 });
    
    return {
        statusCode: 200,
        body: JSON.stringify(session)
    };
};

Rate Limiting

const { Redis } = require('@upstash/redis');

const redis = Redis.fromEnv();

const RATE_LIMIT = 10; // requests per minute
const WINDOW = 60; // seconds

exports.handler = async (event) => {
    const ip = event.requestContext.identity.sourceIp;
    const key = `rate_limit:${ip}`;
    
    // Increment request count
    const requests = await redis.incr(key);
    
    // Set expiration on first request
    if (requests === 1) {
        await redis.expire(key, WINDOW);
    }
    
    // Check if limit exceeded
    if (requests > RATE_LIMIT) {
        return {
            statusCode: 429,
            body: JSON.stringify({
                error: 'Rate limit exceeded',
                retryAfter: await redis.ttl(key)
            })
        };
    }
    
    return {
        statusCode: 200,
        body: JSON.stringify({
            message: 'Request successful',
            remaining: RATE_LIMIT - requests
        })
    };
};

Caching API Responses

const { Redis } = require('@upstash/redis');

const redis = Redis.fromEnv();

exports.handler = async (event) => {
    const userId = event.pathParameters.userId;
    const cacheKey = `user:${userId}`;
    
    // Try to get from cache
    const cached = await redis.get(cacheKey);
    if (cached) {
        return {
            statusCode: 200,
            headers: { 'X-Cache': 'HIT' },
            body: JSON.stringify(cached)
        };
    }
    
    // Fetch from database (simulated)
    const userData = {
        id: userId,
        name: 'John Doe',
        email: '[email protected]',
        fetchedAt: new Date().toISOString()
    };
    
    // Store in cache for 5 minutes
    await redis.set(cacheKey, userData, { ex: 300 });
    
    return {
        statusCode: 200,
        headers: { 'X-Cache': 'MISS' },
        body: JSON.stringify(userData)
    };
};

Best Practices

Use Environment Variables

Always use environment variables for credentials, never hardcode them:
const redis = Redis.fromEnv();
// This automatically reads UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN

Error Handling

const { Redis } = require('@upstash/redis');

const redis = Redis.fromEnv();

exports.handler = async (event) => {
    try {
        const count = await redis.incr("counter");
        return {
            statusCode: 200,
            body: JSON.stringify({ count })
        };
    } catch (error) {
        console.error('Redis error:', error);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: 'Internal server error' })
        };
    }
};

Optimize Cold Starts

Initialize the Redis client outside the handler to reuse connections across warm starts:
const { Redis } = require('@upstash/redis');

// Initialize outside handler
const redis = Redis.fromEnv();

exports.handler = async (event) => {
    // Handler code uses redis client
    const result = await redis.get('key');
    return { statusCode: 200, body: JSON.stringify(result) };
};

Infrastructure as Code

AWS SAM

For AWS SAM examples, see the aws-sam example directory.

AWS CDK

For AWS CDK examples (TypeScript and Python), see:

Terraform

For Terraform deployment examples, see the Terraform example directory.

Testing Locally

Invoke Function Locally

# Set environment variables
export UPSTASH_REDIS_REST_URL="your-url"
export UPSTASH_REDIS_REST_TOKEN="your-token"

# Run with Node.js
node -e "require('./index').handler({}).then(console.log)"

Using AWS SAM CLI

sam local invoke counterFunction --env-vars env.json

Monitoring

CloudWatch Logs

Add logging to track Redis operations:
exports.handler = async (event) => {
    console.log('Processing request:', JSON.stringify(event));
    
    const start = Date.now();
    const count = await redis.incr("counter");
    const duration = Date.now() - start;
    
    console.log(`Redis operation completed in ${duration}ms`);
    
    return {
        statusCode: 200,
        body: JSON.stringify({ count })
    };
};

Troubleshooting

Common Issues

Ensure your Lambda function has internet access. If in a VPC, verify NAT Gateway or VPC endpoints are configured.
Make sure node_modules is included in your deployment package. Run npm install before creating the ZIP file.
Verify environment variables are set in Lambda configuration:
aws lambda get-function-configuration --function-name counterFunction

Next Steps

Cloudflare Workers

Deploy with Cloudflare Workers

Next.js

Use Redis in Next.js applications

Basic Usage

Learn more Redis operations

GitHub Examples

Browse all examples on GitHub

Build docs developers (and LLMs) love