What is Upstash?
Upstash provides serverless Redis and Kafka with HTTP-based APIs. Unlike traditional Redis that requires a persistent TCP connection, Upstash works over HTTP — meaning you can use it from serverless functions, edge workers, and any environment without connection pooling headaches.
Why Upstash?
- Free tier — 10K commands/day for Redis, 10K messages/day for Kafka
- HTTP-based — no persistent connections needed (perfect for serverless)
- Global replication — multi-region for low-latency reads
- Pay per request — $0.2 per 100K commands
- REST API — works from any language, even curl
- QStash — serverless message queue with guaranteed delivery
Quick Start: Redis
npm install @upstash/redis
import { Redis } from '@upstash/redis';
const redis = new Redis({
url: 'https://your-endpoint.upstash.io',
token: 'your-token' // Free at console.upstash.com
});
// Basic operations
await redis.set('user:123', { name: 'Alex', role: 'admin' });
const user = await redis.get('user:123');
// Rate limiting
const requests = await redis.incr('rate:user:123');
await redis.expire('rate:user:123', 60); // Reset every minute
if (requests > 100) throw new Error('Rate limited');
Works Everywhere (HTTP-based)
// Vercel Edge Function
export const config = { runtime: 'edge' };
export default async function handler(req: Request) {
const redis = new Redis({ url: UPSTASH_URL, token: UPSTASH_TOKEN });
const count = await redis.incr('page-views');
return new Response(`Views: ${count}`);
}
// Cloudflare Worker
export default {
async fetch(request, env) {
const redis = new Redis({ url: env.UPSTASH_URL, token: env.UPSTASH_TOKEN });
const cached = await redis.get(`cache:${request.url}`);
if (cached) return new Response(cached);
// ... fetch and cache
}
};
QStash: Serverless Message Queue
import { Client } from '@upstash/qstash';
const qstash = new Client({ token: 'QSTASH_TOKEN' });
// Send a message to be processed
await qstash.publishJSON({
url: 'https://my-app.com/api/process-order',
body: { orderId: '12345', action: 'fulfill' },
retries: 3,
delay: '10s' // Process after 10 seconds
});
// Schedule recurring tasks
await qstash.publishJSON({
url: 'https://my-app.com/api/daily-report',
body: { type: 'daily' },
cron: '0 9 * * *' // Every day at 9 AM
});
Ratelimit SDK
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
});
// In your API handler
const { success, limit, reset, remaining } = await ratelimit.limit('user:123');
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()
}
});
}
Upstash vs Alternatives
| Feature | Upstash | Redis Cloud | AWS ElastiCache | Vercel KV |
|---|---|---|---|---|
| Free tier | 10K cmd/day | 30MB | None | 3K req/day |
| HTTP API | Native | No | No | Uses Upstash |
| Serverless | Yes | Persistent conn | Persistent | Yes |
| Message queue | QStash | Streams | SQS (separate) | No |
| Pay per use | Yes | Fixed plans | Fixed | Yes |
| Global | Multi-region | Single | Single | Global |
Real-World Impact
A Next.js app on Vercel used AWS ElastiCache for caching. Problem: Lambda functions exhausted the Redis connection pool, causing errors under load. After switching to Upstash: HTTP-based connections eliminated pool exhaustion, edge functions could access Redis directly, and the bill dropped from $45/month to $3/month.
Building serverless applications? I help teams implement proper caching and messaging. Contact spinov001@gmail.com or explore my data tools on Apify.
Top comments (0)