Traditional Redis needs a persistent connection. Upstash Redis works over HTTP — perfect for serverless and edge functions.
What is Upstash Redis?
Upstash provides serverless Redis with a REST API. No connection management, no connection pools, no TCP — just HTTP requests.
Free Tier
- 10,000 commands/day
- 256 MB max data size
- Single region
- REST API + Redis protocol
Quick Start
bun add @upstash/redis
import { Redis } from '@upstash/redis';
const redis = new Redis({
url: process.env.UPSTASH_REDIS_URL!,
token: process.env.UPSTASH_REDIS_TOKEN!,
});
// Basic operations
await redis.set('user:123', { name: 'Alice', age: 30 });
const user = await redis.get('user:123');
// With TTL
await redis.set('session:abc', { userId: 123 }, { ex: 3600 }); // expires in 1 hour
// Increment
await redis.incr('page:views');
const views = await redis.get('page:views');
Rate Limiting
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '10 s'), // 10 requests per 10 seconds
analytics: true,
});
export async function middleware(req: Request) {
const ip = req.headers.get('x-forwarded-for') || '127.0.0.1';
const { success, limit, reset, remaining } = await ratelimit.limit(ip);
if (!success) {
return new Response('Too Many Requests', {
status: 429,
headers: {
'X-RateLimit-Limit': limit.toString(),
'X-RateLimit-Remaining': remaining.toString(),
'X-RateLimit-Reset': reset.toString(),
},
});
}
}
Caching
async function getCachedData(key: string, fetcher: () => Promise<any>, ttl = 300) {
const cached = await redis.get(key);
if (cached) return cached;
const data = await fetcher();
await redis.set(key, data, { ex: ttl });
return data;
}
// Usage
const products = await getCachedData(
'products:featured',
() => db.products.findMany({ where: { featured: true } }),
600 // cache for 10 minutes
);
Session Storage
async function createSession(userId: string): Promise<string> {
const sessionId = crypto.randomUUID();
await redis.set(`session:${sessionId}`, { userId, createdAt: Date.now() }, { ex: 86400 });
return sessionId;
}
async function getSession(sessionId: string) {
return await redis.get(`session:${sessionId}`);
}
async function destroySession(sessionId: string) {
await redis.del(`session:${sessionId}`);
}
Works Everywhere (Edge-Compatible)
// Cloudflare Workers
export default {
async fetch(request: Request): Promise<Response> {
const redis = Redis.fromEnv();
await redis.incr('worker:requests');
return new Response('OK');
},
};
// Vercel Edge Functions
import { Redis } from '@upstash/redis';
export const config = { runtime: 'edge' };
export default async function handler(req: Request) {
const redis = Redis.fromEnv();
const count = await redis.incr('edge:visits');
return new Response(`Visit #${count}`);
}
Upstash vs Traditional Redis
| Feature | Upstash Redis | Self-hosted Redis | ElastiCache |
|---|---|---|---|
| Protocol | HTTP + Redis | Redis (TCP) | Redis (TCP) |
| Serverless | Yes | No | No |
| Edge Compatible | Yes | No | No |
| Connection Mgmt | None needed | Required | Required |
| Pricing | Per command | Per server | Per hour |
| Free Tier | 10K cmd/day | N/A | N/A |
Need Redis-backed scraping with caching? Check out my Apify actors — smart caching for efficient data extraction. For custom solutions, email spinov001@gmail.com.
Top comments (0)