465 lines
11 KiB
Markdown
465 lines
11 KiB
Markdown
# Redis Setup on Fly.io
|
|
|
|
This guide covers setting up and managing Redis for LinkForty on Fly.io.
|
|
|
|
## Overview
|
|
|
|
Redis is **optional but highly recommended** for LinkForty. According to the project documentation, Redis caching can reduce database queries by ~90% for repeated link lookups.
|
|
|
|
Fly.io partners with [Upstash](https://upstash.com/) to provide managed Redis with:
|
|
- Serverless pricing (pay per request)
|
|
- Global replication
|
|
- TLS encryption
|
|
- Automatic scaling
|
|
- No idle charges
|
|
|
|
## Creating a Redis Instance
|
|
|
|
### Option 1: Upstash Redis via Fly.io (Recommended)
|
|
|
|
```bash
|
|
fly redis create --name linkforty-redis --region iad
|
|
```
|
|
|
|
You'll be prompted to choose a plan:
|
|
|
|
**Free Tier:**
|
|
- 256MB storage
|
|
- 10,000 commands/day
|
|
- Perfect for development
|
|
- **Cost: $0/month**
|
|
|
|
**Eviction-$10:**
|
|
- 1GB storage
|
|
- 100K commands/day
|
|
- Evicts least-recently-used keys when full
|
|
- **Cost: $10/month**
|
|
|
|
**Eviction-$40:**
|
|
- 5GB storage
|
|
- 500K commands/day
|
|
- Evicts least-recently-used keys when full
|
|
- **Cost: $40/month**
|
|
|
|
**No-Eviction-$120:**
|
|
- 5GB storage
|
|
- 1M commands/day
|
|
- Never evicts keys (blocks writes when full)
|
|
- **Cost: $120/month**
|
|
|
|
### Option 2: Direct Upstash Setup
|
|
|
|
Alternatively, create directly at [Upstash](https://upstash.com/):
|
|
|
|
1. Sign up at https://upstash.com
|
|
2. Create a new Redis database
|
|
3. Choose region (match your Fly.io region)
|
|
4. Select pricing plan
|
|
5. Copy the connection string
|
|
|
|
## Setting Redis URL
|
|
|
|
After creation, you'll receive a `REDIS_URL`. Set it as a secret:
|
|
|
|
```bash
|
|
fly secrets set REDIS_URL="rediss://default:password@host:6379" --app your-linkforty-app
|
|
```
|
|
|
|
**Important:** Use `rediss://` (with double 's') for TLS encryption.
|
|
|
|
## Redis URL Format
|
|
|
|
Your `REDIS_URL` should follow this format:
|
|
|
|
```
|
|
rediss://default:password@host:6379
|
|
```
|
|
|
|
**Components:**
|
|
- `rediss://` - Redis with TLS (**required** for security)
|
|
- `default` - Username (Upstash default)
|
|
- `password` - Authentication token from Upstash
|
|
- `host` - Upstash endpoint (e.g., `xxx-us-east-1.upstash.io`)
|
|
- `6379` - Standard Redis port
|
|
|
|
## Verifying Redis Connection
|
|
|
|
After setting the `REDIS_URL`, deploy and check logs:
|
|
|
|
```bash
|
|
fly deploy
|
|
fly logs
|
|
```
|
|
|
|
Look for:
|
|
```
|
|
Redis connected successfully
|
|
```
|
|
|
|
If Redis is unavailable, LinkForty will still work but will query the database for every link lookup (slower).
|
|
|
|
## How LinkForty Uses Redis
|
|
|
|
### Cache Strategy
|
|
|
|
LinkForty caches link lookups with this pattern:
|
|
|
|
1. **Request:** User visits `https://your-app.fly.dev/abc123`
|
|
2. **Check Redis:** Look for cached link data
|
|
- **Cache hit:** Return immediately (< 5ms)
|
|
- **Cache miss:** Query database, cache result
|
|
3. **TTL:** Cached for 1 hour (configurable)
|
|
|
|
### What Gets Cached
|
|
|
|
- Link metadata (URLs, targeting rules, UTM params)
|
|
- Link expiration status
|
|
- User ID associations
|
|
|
|
### What Doesn't Get Cached
|
|
|
|
- Click events (always written to database)
|
|
- Analytics aggregations
|
|
- Link creation/updates
|
|
|
|
## Performance Benefits
|
|
|
|
With Redis enabled:
|
|
- **Link redirects:** ~5ms (vs ~50-200ms without cache)
|
|
- **Database load:** Reduced by ~90% for popular links
|
|
- **Scalability:** Handle 1000+ req/s on small instances
|
|
|
|
Without Redis:
|
|
- Every redirect hits the database
|
|
- Higher latency for users
|
|
- More database resources needed
|
|
- Lower maximum throughput
|
|
|
|
## Monitoring Redis
|
|
|
|
### Check Connection
|
|
|
|
```bash
|
|
# View app logs
|
|
fly logs --app your-linkforty-app | grep -i redis
|
|
|
|
# Check if REDIS_URL is set
|
|
fly secrets list --app your-linkforty-app
|
|
```
|
|
|
|
### Monitor Usage (Upstash Dashboard)
|
|
|
|
Visit [Upstash Console](https://console.upstash.com/):
|
|
- View daily command count
|
|
- Monitor memory usage
|
|
- Check hit/miss ratio
|
|
- See latency metrics
|
|
|
|
### Redis CLI Access
|
|
|
|
Connect to your Redis instance:
|
|
|
|
```bash
|
|
# Install redis-cli if needed
|
|
brew install redis # macOS
|
|
apt-get install redis-tools # Linux
|
|
|
|
# Connect using REDIS_URL
|
|
redis-cli -u "rediss://default:password@host:6379"
|
|
|
|
# Once connected:
|
|
PING # Should return PONG
|
|
KEYS link:* # List cached links
|
|
GET link:abc123 # View specific cached link
|
|
TTL link:abc123 # Check time-to-live
|
|
INFO stats # View Redis stats
|
|
DBSIZE # Count of keys
|
|
FLUSHDB # ⚠️ Clear all cache (use with caution)
|
|
```
|
|
|
|
## Cache Invalidation
|
|
|
|
### Automatic Invalidation
|
|
|
|
LinkForty automatically invalidates cache when:
|
|
- Link is updated
|
|
- Link is deleted
|
|
- Link expires
|
|
|
|
### Manual Invalidation
|
|
|
|
If needed, clear cache for a specific link:
|
|
|
|
```bash
|
|
redis-cli -u "rediss://default:password@host:6379" DEL link:abc123
|
|
```
|
|
|
|
Clear all cached links:
|
|
|
|
```bash
|
|
redis-cli -u "rediss://default:password@host:6379" FLUSHDB
|
|
```
|
|
|
|
### Cache TTL Configuration
|
|
|
|
Default TTL is 1 hour. To adjust, modify the caching layer in LinkForty:
|
|
|
|
```typescript
|
|
// In your Redis cache implementation
|
|
const TTL = 60 * 60; // 1 hour in seconds
|
|
await redis.set(key, value, 'EX', TTL);
|
|
```
|
|
|
|
Consider:
|
|
- **Short TTL (5-15 min):** More accurate, higher DB load
|
|
- **Long TTL (1-4 hours):** Lower DB load, potentially stale data
|
|
- **No TTL:** Manual invalidation only (not recommended)
|
|
|
|
## Scaling Redis
|
|
|
|
### When to Upgrade
|
|
|
|
Monitor these metrics:
|
|
- **Commands/day approaching limit** → Upgrade plan
|
|
- **Memory usage > 80%** → Upgrade plan or enable eviction
|
|
- **High latency (>10ms)** → Consider global replication
|
|
- **Frequent cache misses** → Increase TTL or memory
|
|
|
|
### Upgrade Plan
|
|
|
|
```bash
|
|
# Via Upstash dashboard
|
|
# https://console.upstash.com/ → Select database → Change plan
|
|
```
|
|
|
|
No downtime during plan changes.
|
|
|
|
### Global Replication (Multi-Region)
|
|
|
|
For lower latency worldwide, enable global replication:
|
|
|
|
1. In Upstash dashboard, enable "Read Replicas"
|
|
2. Choose replica regions (e.g., `us-east`, `eu-west`, `ap-southeast`)
|
|
3. Upstash automatically routes reads to nearest replica
|
|
|
|
**Cost:** ~2x base price per replica region
|
|
|
|
## Security
|
|
|
|
### TLS Encryption
|
|
|
|
Always use `rediss://` (TLS) in production:
|
|
|
|
```bash
|
|
# ✅ Correct (encrypted)
|
|
rediss://default:password@host:6379
|
|
|
|
# ❌ Wrong (unencrypted)
|
|
redis://default:password@host:6379
|
|
```
|
|
|
|
### Password Rotation
|
|
|
|
Rotate Redis password quarterly:
|
|
|
|
1. In Upstash dashboard: **Database → Settings → Reset Password**
|
|
2. Copy new password
|
|
3. Update secret:
|
|
```bash
|
|
fly secrets set REDIS_URL="rediss://default:NEW_PASSWORD@host:6379"
|
|
```
|
|
4. Deploy:
|
|
```bash
|
|
fly deploy
|
|
```
|
|
|
|
### Network Security
|
|
|
|
Upstash Redis is publicly accessible but:
|
|
- Requires authentication (password)
|
|
- Uses TLS encryption
|
|
- Supports IP allowlisting (in Upstash dashboard)
|
|
|
|
For extra security, enable IP allowlisting:
|
|
1. Get your Fly.io app's public IPs: `fly ips list`
|
|
2. In Upstash dashboard: **Settings → IP Allowlist**
|
|
3. Add Fly.io IPs
|
|
|
|
## Troubleshooting
|
|
|
|
### Redis Connection Fails
|
|
|
|
```bash
|
|
# Check REDIS_URL is set correctly
|
|
fly secrets list --app your-linkforty-app
|
|
|
|
# Test connection manually
|
|
redis-cli -u "rediss://default:password@host:6379" PING
|
|
|
|
# Check app logs for errors
|
|
fly logs --app your-linkforty-app | grep -i redis
|
|
```
|
|
|
|
Common issues:
|
|
- Wrong password → Reset in Upstash dashboard
|
|
- Missing `rediss://` protocol → Use TLS version
|
|
- Firewall blocking port 6379 → Check Upstash IP allowlist
|
|
|
|
### High Latency
|
|
|
|
```bash
|
|
# Test latency
|
|
redis-cli -u "rediss://default:password@host:6379" --latency
|
|
|
|
# Check from your app
|
|
redis-cli -u "rediss://default:password@host:6379" SLOWLOG GET 10
|
|
```
|
|
|
|
Solutions:
|
|
- Enable global replication for multi-region apps
|
|
- Check Upstash status page
|
|
- Verify region matches your app region
|
|
|
|
### Memory Full (Eviction Errors)
|
|
|
|
```bash
|
|
# Check memory usage
|
|
redis-cli -u "rediss://default:password@host:6379" INFO memory
|
|
|
|
# Check eviction stats
|
|
redis-cli -u "rediss://default:password@host:6379" INFO stats | grep evicted
|
|
```
|
|
|
|
Solutions:
|
|
- Upgrade to larger plan
|
|
- Reduce cache TTL
|
|
- Implement selective caching (only cache popular links)
|
|
|
|
### Cache Hit Rate Too Low
|
|
|
|
```bash
|
|
# Check hit rate
|
|
redis-cli -u "rediss://default:password@host:6379" INFO stats
|
|
# Look for: keyspace_hits and keyspace_misses
|
|
```
|
|
|
|
Low hit rate causes:
|
|
- TTL too short
|
|
- Traffic pattern (mostly unique links)
|
|
- Not enough memory (evictions)
|
|
|
|
Solutions:
|
|
- Increase TTL (if data staleness is acceptable)
|
|
- Increase memory (upgrade plan)
|
|
- Profile which links are being accessed
|
|
|
|
## Running Without Redis
|
|
|
|
LinkForty works without Redis, but with performance trade-offs:
|
|
|
|
### Performance Without Redis
|
|
|
|
- **Latency:** ~50-200ms per redirect (vs ~5ms with Redis)
|
|
- **Database load:** 10x higher
|
|
- **Throughput:** Lower maximum requests/second
|
|
- **Costs:** Higher database instance needed
|
|
|
|
### Disabling Redis
|
|
|
|
Simply don't set `REDIS_URL`:
|
|
|
|
```bash
|
|
fly secrets unset REDIS_URL --app your-linkforty-app
|
|
```
|
|
|
|
LinkForty detects missing Redis and falls back to database-only mode.
|
|
|
|
### When to Skip Redis
|
|
|
|
Skip Redis if:
|
|
- Very low traffic (< 100 redirects/day)
|
|
- Budget is extremely tight
|
|
- All links are unique (no repeated lookups)
|
|
- Development/testing only
|
|
|
|
## Cost Optimization
|
|
|
|
### Free Tier (Good for Development)
|
|
- 256MB storage
|
|
- 10,000 commands/day
|
|
- ~300 redirects/day with caching
|
|
- **Cost: $0/month**
|
|
|
|
### Small Production ($10/month)
|
|
- 1GB storage
|
|
- 100K commands/day
|
|
- ~3,000 redirects/day with caching
|
|
- **Cost: $10/month**
|
|
|
|
### Estimate Your Needs
|
|
|
|
Calculate commands/day:
|
|
- Link redirect with cache hit: 1 command (`GET`)
|
|
- Link redirect with cache miss: 2 commands (`GET` + `SET`)
|
|
- Assume 50% hit rate: 1.5 commands per redirect
|
|
- For 10,000 redirects/day: ~15,000 commands/day
|
|
|
|
Choose plan accordingly.
|
|
|
|
### Cost Monitoring
|
|
|
|
```bash
|
|
# In Upstash dashboard
|
|
# View: Billing → Current Usage
|
|
```
|
|
|
|
Set up alerts for:
|
|
- 80% of command limit reached
|
|
- 80% of storage used
|
|
|
|
## Alternative: Self-Hosted Redis
|
|
|
|
Instead of Upstash, you can run Redis on Fly.io:
|
|
|
|
### Create Redis Machine
|
|
|
|
```bash
|
|
fly launch --image redis:7-alpine --name linkforty-redis --region iad
|
|
```
|
|
|
|
**Pros:**
|
|
- Lower cost for high traffic
|
|
- Full control
|
|
|
|
**Cons:**
|
|
- You manage backups
|
|
- You manage security
|
|
- No automatic scaling
|
|
- More operational overhead
|
|
|
|
**Not recommended** unless you have specific requirements or very high traffic (>1M commands/day).
|
|
|
|
## Best Practices
|
|
|
|
1. **Always use TLS** (`rediss://`)
|
|
2. **Set reasonable TTL** (1-4 hours for links)
|
|
3. **Monitor hit rate** (target >70%)
|
|
4. **Rotate passwords** quarterly
|
|
5. **Enable global replication** for multi-region deployments
|
|
6. **Set up alerts** for command limits
|
|
7. **Start small** (free tier) and scale up based on metrics
|
|
|
|
## Resources
|
|
|
|
- [Upstash Documentation](https://docs.upstash.com/redis)
|
|
- [Redis Documentation](https://redis.io/documentation)
|
|
- [Fly.io Redis Guide](https://fly.io/docs/reference/redis/)
|
|
- [Cache Invalidation Strategies](https://redis.io/docs/manual/keyspace-notifications/)
|
|
|
|
---
|
|
|
|
**Need Help?**
|
|
- Upstash Support: https://upstash.com/docs/redis/support
|
|
- Redis Community: https://redis.io/community
|
|
- Fly.io Community: https://community.fly.io/
|