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: 'john@example.com',
        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