chore: archive inactive projects to apps-archived/

Move inactive projects out of active workspace:
- bauntown (community website)
- maerchenzauber (AI story generation)
- memoro (voice memo app)
- news (news aggregation)
- nutriphi (nutrition tracking)
- reader (reading app)
- uload (URL shortener)
- wisekeep (AI wisdom extraction)

Update CLAUDE.md documentation:
- Add presi to active projects
- Document archived projects section
- Update workspace configuration

Archived apps can be re-activated by moving back to apps/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-11-29 07:03:59 +01:00
parent b97149ac12
commit 61d181fbc2
3148 changed files with 437 additions and 46640 deletions

View file

@ -0,0 +1,513 @@
Redis Cache für uLoad - Was bringt es
wirklich?
Das Hauptproblem aktuell
Jedes Mal wenn jemand einen deiner
Short-Links klickt, muss deine App:
1. PocketBase fragen "welche URL gehört zu
diesem Short-Code?"
2. Warten bis PocketBase in der SQLite
Datei sucht
3. Antwort zurückgeben und weiterleiten
Das dauert 50-100ms pro Klick. Bei vielen
Klicks wird PocketBase zum Flaschenhals.
Was Redis ändern würde
Redis ist wie ein ultra-schneller
Zwischenspeicher. Statt jedes Mal
PocketBase zu fragen, schaust du erst in
Redis nach. Das ist 20-50x schneller!
Die 3 größten Verbesserungen
1. Link-Redirects (90% deines Traffics)
Problem: Jeder Klick = PocketBase Query =
langsam
Lösung: Beliebte Links werden in Redis
gespeichert
Beispiel:
- Dein Link "ulo.ad/meeting" wird 100x am
Tag geklickt
- Ohne Redis: 100x PocketBase Query (100x
80ms = 8 Sekunden Serverzeit)
- Mit Redis: 1x PocketBase + 99x Redis (1x
80ms + 99x 2ms = 0.28 Sekunden)
Ergebnis: 30x schneller, 95% weniger
PocketBase Last
2. Dashboard Performance
Problem: Dein Dashboard lädt alle deine
Links aus PocketBase
Lösung: Links werden für 5 Minuten gecacht
Beispiel:
- Du hast 50 Links, checkst Dashboard 20x
am Tag
- Ohne Redis: 20x komplette Liste laden =
langsam
- Mit Redis: 1x laden, 19x aus Cache =
blitzschnell
3. Analytics & Statistiken
Problem: Click-Zahlen berechnen ist langsam
(viele Datenbankabfragen)
Lösung: Statistiken werden live berechnet
und gecacht
Beispiel:
- "Zeige Clicks der letzten 7 Tage" braucht
normalerweise komplizierte Queries
- Mit Redis: Zahlen werden kontinuierlich
aktualisiert, sofort verfügbar
Rate Limiting Verbesserung
Aktuell: Dein Rate Limiter vergisst alles
bei Server-Restart
Mit Redis: Rate Limits bleiben bestehen,
auch über Restarts hinweg
Das bedeutet: Angreifer können nicht mehr
durch Server-Restart deine Limits umgehen.
Konkrete Zahlen für dich
Traffic-Verteilung schätzen:
- 90% Redirects (Leute klicken deine Links)
- 8% Dashboard/API (Du managst deine Links)
- 2% Sonstiges (Login, Settings, etc.)
Performance ohne Redis:
- Redirect: 80ms durchschnittlich
- Dashboard laden: 300ms
- Bei 1000 Klicks/Tag: PocketBase ist
gestresst
Performance mit Redis:
- Redirect: 5ms (95% aus Cache)
- Dashboard laden: 20ms (meist aus Cache)
- Bei 10.000 Klicks/Tag: PocketBase
entspannt
Wann merkst du den Unterschied?
Sofort spürbar:
- Dashboard lädt viel schneller (besonders
mit vielen Links)
- Redirects sind blitzschnell
- Analytics laden sofort statt zu "denken"
Bei mehr Traffic:
- Server bleibt entspannt auch bei
Viral-Links
- Keine Timeouts mehr bei hoher Last
- PocketBase überlastet nicht
Skalierung:
- Ohne Redis: ~500 Redirects/Minute machbar
- Mit Redis: ~5000+ Redirects/Minute
machbar
Kosten vs. Nutzen
Option 1: Kostenlos starten
- Upstash Redis (10k Commands/Tag gratis)
- Perfekt zum Testen
- Upgrade wenn nötig
Option 2: Minimale Kosten
- €5-15/Monat für ordentlichen Redis
- Dafür 10x bessere Performance
Was du sparst:
- Weniger Server-Stress = längere
Hardware-Lebensdauer
- Bessere User Experience = mehr zufriedene
Nutzer
- Skalierung möglich ohne neuen Server
Die Realität für uLoad
Jetzt: Bei 100 Klicks gleichzeitig würde
dein Server wahrscheinlich strugglen
Mit Redis: Bei 1000 Klicks gleichzeitig
läuft alles smooth
Jetzt: Dashboard mit 100 Links braucht eine
Sekunde zum Laden
Mit Redis: Dashboard lädt in 0.1 Sekunden
Jetzt: Click-Statistiken berechnen dauert
ewig
Mit Redis: Statistiken sind immer aktuell
und sofort da
Meine ehrliche Einschätzung
Für uLoad ist Redis ein No-Brainer:
- Minimaler Aufwand (2-3 Tage Setup)
- Maximaler Nutzen (10x Performance)
- Kosten fast null (kann gratis starten)
Der größte Gewinn ist bei Redirects - das
ist dein Kernfeature und wird damit
ultra-schnell. Plus du bist ready für
Viral-Links die plötzlich 1000x geklickt
werden.
Bottom Line: Redis macht aus deinem "hobby
project" eine professionelle, skalierbare
Anwendung für praktisch null Zusatzkosten.
Das ist vermutlich das beste ROI was du
kriegen kannst! 🎯
> super danke. wir können ja reddis auch
> einfach auf unserem hetzter vps mit coolify
> hochfahren oder? was brucht es an
> reccourcen? was mus man beachten? sollte es
> lieber auf einem adnere server liegen?
> sollte es im gleichen project in coolify
> liegen?
⏺ Redis auf Hetzner VPS mit Coolify -
Perfekte Idee!
Ja, absolut machbar und sinnvoll!
Dein aktueller Hetzner VPS kann Redis
problemlos mit hosten. Coolify macht das
super einfach.
Resource-Bedarf von Redis
RAM (das Wichtigste):
- Redis lädt alles in den RAM - das macht
es so schnell
- Für uLoad geschätzt: 50-200MB RAM
- Link Cache: ~1MB pro 10.000 Links
- Session Cache: ~10MB für 1000 aktive
User
- Analytics: ~20-50MB je nach History
- Rate Limiting: ~5-10MB
CPU:
- Minimal! Redis ist extrem CPU-effizient
- Für uLoad: <1% CPU Auslastung
- Nur bei komplexen Operationen mehr
Disk:
- Persistence: 100-500MB für Dumps
- Logs: 10-50MB
- Total: <1GB
Dein CX21 VPS Kapazität:
- RAM: 8GB total, aktuell ~2GB verwendet →
6GB frei!
- CPU: 2 vCPUs, aktuell <20% Mehr als
genug
- Disk: 40GB, Redis braucht <1GB Kein
Problem
Fazit: Dein Server kann Redis locker
verkraften! 🎯
Coolify Setup - zwei Optionen
Option 1: Gleiches Projekt (Empfohlen für
Start)
# Einfach Redis Service zu deinem
bestehenden docker-compose hinzufügen
services:
app: # Deine bestehende App
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
--maxmemory 512mb --maxmemory-policy
allkeys-lru
volumes: - redis-data:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
volumes:
redis-data:
Option 2: Separates Projekt in Coolify
- Vorteil: Unabhängiges Deployment von
deiner App
- Nachteil: Etwas komplizierter zu
verwalten
Ich empfehle Option 1 - Redis ist so
stabil, das macht keinen Unterschied.
Coolify Konfiguration
Redis Environment Variables:
# In Coolify für Redis Service setzen:
REDIS_PASSWORD=dein-sicheres-passwort-hier
REDIS_MAXMEMORY=512mb
REDIS_SAVE_INTERVAL=900 # Auto-save alle
15 Min
Deine App erweitern:
# Environment Variable für deine App
hinzufügen:
REDIS_URL=redis://:dein-passwort@redis:6379
Networking in Coolify:
- Redis und App sind automatisch im
gleichen Docker Network
- Deine App kann Redis über redis:6379
erreichen
- Kein Port nach außen öffnen nötig
(Sicherheit!)
Wichtige Redis Konfiguration
Memory Management:
# Redis Config (über Command Parameter):
--maxmemory 512mb # Begrenze RAM Nutzung
--maxmemory-policy allkeys-lru # Alte Keys
löschen wenn voll
Persistence:
# Zwei Optionen kombinieren:
--appendonly yes # AOF für Durability
--save 900 1 # RDB Snapshot alle 15
Min
Security:
# Passwort setzen:
--requirepass dein-starkes-passwort
# Gefährliche Commands deaktivieren:
--rename-command FLUSHDB ""
--rename-command FLUSHALL ""
Monitoring in Coolify
Redis Logs überwachen:
- Coolify zeigt Redis Logs in Echtzeit
- Achte auf Memory Warnings
- Connection Errors beobachten
Wichtige Redis Metriken:
# Commands zum Monitoring (über redis-cli):
INFO memory # RAM Nutzung
INFO stats # Operations/sec
INFO clients # Verbindungen
MONITOR # Live Commands (nur
zum Debugging!)
Backup Strategy
Automatische Redis Backups:
# Script in deinem Container:
#!/bin/bash
# redis-backup.sh
DATE=$(date +%Y%m%d_%H%M%S)
redis-cli --rdb
/backups/redis_backup_$DATE.rdb
# In Coolify als Cron Job alle 6 Stunden
Oder einfacher:
# Volume Mount für Persistence reicht:
volumes: - redis-data:/data # Redis saved
automatisch hier
Separater Server - wann sinnvoll?
Bleib bei einem Server wenn:
- <10.000 Requests/Tag (definitiv dein
Fall)
- <1000 gleichzeitige User
- Development/Early Stage (definitiv dein
Fall)
Separater Redis Server nur bei:
- > 100.000 Requests/Tag
- Multi-Region Setup
- Dedicated Redis Cluster mit Failover
Für uLoad: Ein Server reicht völlig!
Coolify Deployment Steps
1. Docker Compose erweitern:
# Zu deiner bestehenden docker-compose.yml
hinzufügen:
services: # ... deine bestehenden Services
redis:
image: redis:7-alpine
command: >
redis-server
--appendonly yes
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
restart: unless-stopped
networks:
- app-network
healthcheck:
test: ["CMD", "redis-cli", "-a",
"${REDIS_PASSWORD}", "ping"]
interval: 30s
timeout: 10s
retries: 3
volumes:
redis-data:
networks:
app-network:
driver: bridge
2. Environment Variables in Coolify:
# Für Redis:
REDIS_PASSWORD=SuperSecurePassword123!
# Für deine App:
REDIS_URL=redis://:SuperSecurePassword123!@
redis:6379
3. Deploy & Test:
- Coolify deployed automatisch
- Teste Connection aus deiner App
- Check Redis Logs für Errors
Was beachten?
Security:
- Passwort setzen (Redis hat standardmäßig
keins!)
- Port nicht öffentlich machen (nur intern)
- Command Renaming für gefährliche Commands
Performance:
- Memory Limit setzen (512MB reicht für
Start)
- LRU Policy aktivieren (alte Keys werden
gelöscht)
- Connection Pooling in deiner App
Monitoring:
- Redis Logs in Coolify beobachten
- Memory Usage im Auge behalten
- Hit Rate messen (wie oft Cache getroffen
wird)
Troubleshooting
Häufige Probleme:
1. Connection refused: Redis Service nicht
gestartet
2. Auth failed: Passwort falsch oder nicht
gesetzt
3. Memory full: Maxmemory erreicht, LRU
Policy prüfen
Debug Commands:
# In Coolify Terminal (Redis Container):
redis-cli -a dein-passwort info
redis-cli -a dein-passwort ping
redis-cli -a dein-passwort client list
Meine Empfehlung
Setup für uLoad:
1. Gleicher Server (Hetzner VPS) ✅
2. Gleiches Coolify Projekt ✅
3. 512MB Memory Limit ✅
4. Passwort-geschützt ✅
5. Persistence aktiviert ✅
Vorteile:
- Einfachste Lösung
- Keine Extra-Kosten
- Latenz minimal (gleicher Server)
- Easy zu verwalten
Nachteile:
- Keine (für deine Use Case)
Redis auf deinem bestehenden Setup ist der
perfekte nächste Schritt! 🚀

View file

@ -0,0 +1,185 @@
Redis Cache für uLoad - Was bringt es
wirklich?
Das Hauptproblem aktuell
Jedes Mal wenn jemand einen deiner
Short-Links klickt, muss deine App:
1. PocketBase fragen "welche URL gehört zu
diesem Short-Code?"
2. Warten bis PocketBase in der SQLite
Datei sucht
3. Antwort zurückgeben und weiterleiten
Das dauert 50-100ms pro Klick. Bei vielen
Klicks wird PocketBase zum Flaschenhals.
Was Redis ändern würde
Redis ist wie ein ultra-schneller
Zwischenspeicher. Statt jedes Mal
PocketBase zu fragen, schaust du erst in
Redis nach. Das ist 20-50x schneller!
Die 3 größten Verbesserungen
1. Link-Redirects (90% deines Traffics)
Problem: Jeder Klick = PocketBase Query =
langsam
Lösung: Beliebte Links werden in Redis
gespeichert
Beispiel:
- Dein Link "ulo.ad/meeting" wird 100x am
Tag geklickt
- Ohne Redis: 100x PocketBase Query (100x
80ms = 8 Sekunden Serverzeit)
- Mit Redis: 1x PocketBase + 99x Redis (1x
80ms + 99x 2ms = 0.28 Sekunden)
Ergebnis: 30x schneller, 95% weniger
PocketBase Last
2. Dashboard Performance
Problem: Dein Dashboard lädt alle deine
Links aus PocketBase
Lösung: Links werden für 5 Minuten gecacht
Beispiel:
- Du hast 50 Links, checkst Dashboard 20x
am Tag
- Ohne Redis: 20x komplette Liste laden =
langsam
- Mit Redis: 1x laden, 19x aus Cache =
blitzschnell
3. Analytics & Statistiken
Problem: Click-Zahlen berechnen ist langsam
(viele Datenbankabfragen)
Lösung: Statistiken werden live berechnet
und gecacht
Beispiel:
- "Zeige Clicks der letzten 7 Tage" braucht
normalerweise komplizierte Queries
- Mit Redis: Zahlen werden kontinuierlich
aktualisiert, sofort verfügbar
Rate Limiting Verbesserung
Aktuell: Dein Rate Limiter vergisst alles
bei Server-Restart
Mit Redis: Rate Limits bleiben bestehen,
auch über Restarts hinweg
Das bedeutet: Angreifer können nicht mehr
durch Server-Restart deine Limits umgehen.
Konkrete Zahlen für dich
Traffic-Verteilung schätzen:
- 90% Redirects (Leute klicken deine Links)
- 8% Dashboard/API (Du managst deine Links)
- 2% Sonstiges (Login, Settings, etc.)
Performance ohne Redis:
- Redirect: 80ms durchschnittlich
- Dashboard laden: 300ms
- Bei 1000 Klicks/Tag: PocketBase ist
gestresst
Performance mit Redis:
- Redirect: 5ms (95% aus Cache)
- Dashboard laden: 20ms (meist aus Cache)
- Bei 10.000 Klicks/Tag: PocketBase
entspannt
Wann merkst du den Unterschied?
Sofort spürbar:
- Dashboard lädt viel schneller (besonders
mit vielen Links)
- Redirects sind blitzschnell
- Analytics laden sofort statt zu "denken"
Bei mehr Traffic:
- Server bleibt entspannt auch bei
Viral-Links
- Keine Timeouts mehr bei hoher Last
- PocketBase überlastet nicht
Skalierung:
- Ohne Redis: ~500 Redirects/Minute machbar
- Mit Redis: ~5000+ Redirects/Minute
machbar
Kosten vs. Nutzen
Option 1: Kostenlos starten
- Upstash Redis (10k Commands/Tag gratis)
- Perfekt zum Testen
- Upgrade wenn nötig
Option 2: Minimale Kosten
- €5-15/Monat für ordentlichen Redis
- Dafür 10x bessere Performance
Was du sparst:
- Weniger Server-Stress = längere
Hardware-Lebensdauer
- Bessere User Experience = mehr zufriedene
Nutzer
- Skalierung möglich ohne neuen Server
Die Realität für uLoad
Jetzt: Bei 100 Klicks gleichzeitig würde
dein Server wahrscheinlich strugglen
Mit Redis: Bei 1000 Klicks gleichzeitig
läuft alles smooth
Jetzt: Dashboard mit 100 Links braucht eine
Sekunde zum Laden
Mit Redis: Dashboard lädt in 0.1 Sekunden
Jetzt: Click-Statistiken berechnen dauert
ewig
Mit Redis: Statistiken sind immer aktuell
und sofort da
Meine ehrliche Einschätzung
Für uLoad ist Redis ein No-Brainer:
- Minimaler Aufwand (2-3 Tage Setup)
- Maximaler Nutzen (10x Performance)
- Kosten fast null (kann gratis starten)
Der größte Gewinn ist bei Redirects - das
ist dein Kernfeature und wird damit
ultra-schnell. Plus du bist ready für
Viral-Links die plötzlich 1000x geklickt
werden.
Bottom Line: Redis macht aus deinem "hobby
project" eine professionelle, skalierbare
Anwendung für praktisch null Zusatzkosten.
Das ist vermutlich das beste ROI was du
kriegen kannst! 🎯

View file

@ -0,0 +1,302 @@
# Redis Cache Architecture
## System Overview
uload uses Redis as a high-performance caching layer to accelerate link redirects and reduce database load.
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Browser │────▶│ SvelteKit │────▶│ Redis │
└─────────────┘ │ Server │ └─────────────┘
└─────────────┘ │
│ │ Cache Miss
│ ▼
│ ┌─────────────┐
└───────────▶│ PocketBase │
└─────────────┘
```
## Cache Implementation
### File Structure
```
src/lib/server/
├── redis.ts # Redis client configuration and helpers
└── linkCache.ts # Link-specific caching logic
src/routes/
├── [...slug]/
│ └── +page.server.ts # Link redirect with cache
└── api/
└── redis-status/
└── +server.ts # Redis health check endpoint
```
### Core Components
#### 1. Redis Client (`redis.ts`)
Provides a fault-tolerant Redis connection with automatic fallback:
```typescript
// Connection detection
const REDIS_ENABLED = !!(
process.env.REDIS_HOST &&
(process.env.REDIS_PASSWORD || process.env.NODE_ENV === 'development')
);
// Graceful degradation
if (!redis || !redisAvailable) return null;
```
#### 2. Link Cache (`linkCache.ts`)
Implements caching strategies for different link types:
```typescript
class LinkCache {
// Fast redirect caching
async getRedirectUrl(shortCode: string): Promise<string | null>
async cacheRedirect(shortCode: string, targetUrl: string, popular: boolean)
// Full object caching
async cacheLink(link: Link): Promise<void>
async getLink(shortCode: string): Promise<Link | null>
// Cache management
async invalidate(shortCode: string): Promise<void>
async warmCache(links: Link[]): Promise<void>
}
```
## Cache Strategy
### TTL (Time To Live) Policy
| Content Type | TTL | Reason |
|-------------|-----|---------|
| Popular Links | 24 hours | Frequently accessed, rarely changed |
| Normal Links | 5 minutes | Balance between performance and freshness |
| User Link Lists | 5 minutes | May change frequently |
| Password-Protected | Never cached | Security requirement |
| Expired Links | Never cached | Would bypass expiration check |
### Cache Key Patterns
```
redirect:{shortCode} # Direct URL for fast redirects
link:{shortCode} # Full link object with metadata
clicks:{shortCode} # Click counter
user:{userId}:links:page:{n} # Paginated user links
trending:links # Sorted set for analytics
test:ping # Health check key
```
### Cache Warming
Popular links are pre-loaded into cache on startup:
```typescript
async warmCache(links: Link[]): Promise<void> {
for (const link of links) {
await this.cacheRedirect(link.short_code, link.original_url, true);
}
}
```
## Performance Optimization
### 1. Cache-First Strategy
```typescript
// Check cache first (fastest path)
const cachedUrl = await linkCache.getRedirectUrl(shortCode);
if (cachedUrl) {
throw redirect(302, cachedUrl);
}
// Fall back to database
const link = await locals.pb.collection('links').getFirstListItem(...);
```
### 2. Async Cache Population
Cache writes are non-blocking to maintain low latency:
```typescript
// Cache for next time (non-blocking)
if (link.is_active && !link.password) {
await linkCache.cacheRedirect(shortCode, link.original_url);
}
```
### 3. Trending Analytics
Click tracking without blocking redirects:
```typescript
// Async increment hit counter (non-blocking)
this.incrementHitCount(shortCode).catch(console.error);
```
## Fallback Mechanism
### Graceful Degradation
The system continues functioning without Redis:
1. **Detection**: Check Redis availability on startup
2. **Fallback**: Skip cache operations if unavailable
3. **Recovery**: Attempt reconnection periodically
4. **Logging**: Track cache availability for monitoring
### Error Handling
All cache operations are wrapped in try-catch blocks:
```typescript
try {
await ensureRedisConnection();
// Cache operations...
} catch (error) {
console.error('Cache error:', error);
return null; // Continue without cache
}
```
## Security Considerations
### 1. No Sensitive Data Caching
- Password-protected links bypass cache
- User authentication tokens never cached
- Personal data has minimal TTL
### 2. Cache Invalidation
Links are invalidated when:
- Link is updated
- Link is deleted
- Password protection added
- Expiration date reached
### 3. Rate Limiting
Redis enables efficient rate limiting:
```typescript
const key = `rate:${ip}:${endpoint}`;
const count = await cache.incr(key);
if (count === 1) {
await cache.expire(key, 60); // 1 minute window
}
```
## Monitoring & Debugging
### Health Check Endpoint
`GET /api/redis-status`
```json
{
"connected": true,
"host": "localhost",
"enabled": true,
"available": true,
"cachedLinks": 42,
"error": null
}
```
### Console Logging
Development mode provides detailed logs:
```
✅ Redis: Connected successfully
Cache HIT! Redirecting from cache
Cache MISS - fetching from PocketBase
Cached redirect for future use
```
### Performance Metrics
Track cache effectiveness:
```typescript
// Hit rate calculation
const hits = await redis.get('stats:cache:hits') || 0;
const misses = await redis.get('stats:cache:misses') || 0;
const hitRate = hits / (hits + misses) * 100;
```
## Production Considerations
### 1. Memory Management
```bash
# Set max memory in Redis config
maxmemory 256mb
maxmemory-policy allkeys-lru
```
### 2. Persistence Options
```bash
# Disable persistence for cache-only use
save ""
appendonly no
```
### 3. Connection Pooling
```typescript
const redisConfig = {
retryDelayOnFailover: 100,
maxRetriesPerRequest: 3,
enableOfflineQueue: false,
lazyConnect: true
};
```
### 4. Monitoring Setup
- Use Redis INFO command for metrics
- Set up alerts for connection failures
- Monitor memory usage and eviction rate
- Track cache hit/miss ratio
## Scaling Strategies
### Horizontal Scaling
1. **Redis Cluster**: Distribute cache across nodes
2. **Read Replicas**: Separate read/write operations
3. **Sharding**: Partition by link patterns
### Vertical Scaling
1. **Memory**: Increase Redis memory allocation
2. **CPU**: Optimize for single-threaded performance
3. **Network**: Reduce latency with proximity
## Future Enhancements
### Planned Improvements
1. **Smart Preloading**: ML-based prediction of popular links
2. **Geolocation Caching**: CDN-style distributed cache
3. **Real-time Analytics**: Stream processing with Redis Streams
4. **Cache Warming API**: Admin endpoint for cache management
5. **A/B Testing**: Cache different versions for experiments
### Performance Goals
| Metric | Current | Target |
|--------|---------|--------|
| Cache Hit Rate | 70% | 90% |
| Redirect Latency | 20ms | 10ms |
| Memory Usage | 100MB | 50MB |
| TTL Optimization | Static | Dynamic |

View file

@ -0,0 +1,279 @@
# Redis Setup auf Coolify - Complete Guide
## Erfolgreiche Redis Integration für uLoad
Nach einigen Herausforderungen haben wir Redis erfolgreich auf Coolify zum Laufen gebracht. Hier sind die wichtigsten Learnings und die funktionierende Konfiguration.
## ✅ Funktionierende Konfiguration
### Redis Service in Coolify
#### 1. Redis als Database Service hinzufügen
- **Type:** Redis Database
- **Image:** redis:7.2
- **Name:** redis-database-[generated-id]
#### 2. General Settings
```
Username: default
Password: [Sicheres Passwort generieren]
Custom Docker Options: --protected-mode no --bind 0.0.0.0
```
**Wichtig:** Die Custom Docker Options sind KRITISCH! Ohne diese wird Redis Verbindungen ablehnen.
#### 3. Network Configuration
```
Ports Mappings: 6379:6379
Redis URL (internal): [wird automatisch generiert]
```
**Achtung:** Nicht 5432 verwenden (das ist PostgreSQL)!
### Hauptanwendung Environment Variables
#### Funktionierende Konfiguration:
```bash
REDIS_HOST=ycsoowwsc84s0s8gc8oooosk # Der Container-Name (NICHT der Service-Name!)
REDIS_PORT=6379
REDIS_USERNAME=default
REDIS_PASSWORD=[Das gleiche Passwort wie im Redis Service]
```
## 🔍 Wichtige Erkenntnisse
### 1. Container Name vs. Service Name
**Problem:** Der Coolify Service Name funktioniert nicht für die interne Kommunikation.
**Lösung:** Verwende den tatsächlichen Container-Namen:
- ❌ FALSCH: `redis-database-ycsoowwsc84s0s8gc8oooosk`
- ❌ FALSCH: `redis-database-ycsoowwsc84s0s8gc8oooosk.coolify`
- ✅ RICHTIG: `ycsoowwsc84s0s8gc8oooosk`
Der Container-Name findest du in den Redis Logs oder beim Container Start.
### 2. Protected Mode Problem
**Problem:** "Connection is closed" Fehler trotz korrekter Credentials.
**Lösung:** Redis Protected Mode deaktivieren:
```bash
--protected-mode no --bind 0.0.0.0
```
Diese Optionen MÜSSEN in "Custom Docker Options" gesetzt werden!
### 3. Environment Variables Format
**Problem:** REDIS_HOST wurde mit kompletter URL statt nur Hostname gesetzt.
**Lösung:**
- ❌ FALSCH: `REDIS_HOST=redis://default:password@host:6379`
- ✅ RICHTIG: `REDIS_HOST=ycsoowwsc84s0s8gc8oooosk`
REDIS_HOST darf NUR der Hostname sein, keine URL!
### 4. Port Mapping Confusion
**Problem:** Falscher Port (5432 statt 6379) wurde gemappt.
**Lösung:**
- Port 6379 ist Redis
- Port 5432 ist PostgreSQL
- Immer 6379:6379 für Redis verwenden
## 📋 Komplette Setup-Anleitung
### Schritt 1: Redis Service erstellen
1. In Coolify → New Resource → Database → Redis
2. Wähle redis:7.2 als Image
3. Setze Username: `default`
4. Generiere ein starkes Passwort
5. **WICHTIG:** Custom Docker Options: `--protected-mode no --bind 0.0.0.0`
6. Port Mapping: `6379:6379`
7. Deploy
### Schritt 2: Container Name ermitteln
1. Gehe zu Redis Service → Logs
2. Suche nach Container Name (z.B. `ycsoowwsc84s0s8gc8oooosk`)
3. Notiere diesen Namen!
### Schritt 3: Hauptapp konfigurieren
Environment Variables in deiner Hauptapp:
```bash
REDIS_HOST=[Container-Name aus Schritt 2]
REDIS_PORT=6379
REDIS_USERNAME=default
REDIS_PASSWORD=[Passwort aus Redis Service]
```
### Schritt 4: Testen
Erstelle einen Test-Endpoint in deiner App:
```typescript
// src/routes/test-redis/+server.ts
import { json } from '@sveltejs/kit';
import Redis from 'ioredis';
export async function GET() {
const redis = new Redis({
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379'),
username: process.env.REDIS_USERNAME,
password: process.env.REDIS_PASSWORD,
});
try {
await redis.ping();
await redis.set('test', 'Hello Redis!');
const value = await redis.get('test');
redis.disconnect();
return json({
success: true,
value,
host: process.env.REDIS_HOST,
});
} catch (error) {
return json(
{
success: false,
error: error.message,
},
{ status: 500 }
);
}
}
```
## 🚀 Performance-Verbesserungen
Nach erfolgreicher Redis-Integration:
### Link Redirects
- **Vorher:** 50-100ms (PocketBase Query)
- **Nachher:** 2-5ms (Redis Cache)
- **Verbesserung:** 20-50x schneller!
### Dashboard Loading
- **Vorher:** 200-400ms
- **Nachher:** 10-20ms
- **Verbesserung:** 10-20x schneller!
### Analytics
- **Vorher:** 500-1500ms
- **Nachher:** 20-50ms
- **Verbesserung:** 10-30x schneller!
## 🐛 Troubleshooting
### "Connection is closed" Error
1. Check Custom Docker Options: `--protected-mode no --bind 0.0.0.0`
2. Verify Container Name (nicht Service Name!)
3. Check Password ist korrekt
### "ECONNREFUSED" Error
1. Redis Service läuft nicht
2. Falscher Host/Port
3. Network Isolation Problem
### "NOAUTH Authentication required"
1. Password nicht gesetzt in Environment Variables
2. Falsches Password
3. Username fehlt (sollte "default" sein)
### Debug Commands
Im Redis Container (via Coolify Terminal):
```bash
# Test Redis läuft
redis-cli ping
# Mit Auth
redis-cli -a [password] ping
# Check Config
redis-cli -a [password] CONFIG GET bind
redis-cli -a [password] CONFIG GET protected-mode
```
## 💡 Best Practices
### 1. Resource Limits
```bash
--maxmemory 512mb
--maxmemory-policy allkeys-lru
```
### 2. Persistence
```bash
--appendonly yes
--save 900 1 # Save every 15 min if at least 1 key changed
```
### 3. Security
- Niemals Redis Port öffentlich exponieren
- Starkes Passwort verwenden
- Protected Mode nur intern deaktivieren
### 4. Monitoring
- Memory Usage im Auge behalten
- Hit Rate tracken
- Slow Queries monitoren
## 📊 Resource-Bedarf
Für uLoad auf Hetzner CX21:
- **RAM:** 50-200MB (von 8GB verfügbar)
- **CPU:** <1% (von 2 vCPUs)
- **Disk:** <1GB (von 40GB)
Redis ist extrem ressourcen-effizient!
## 🎯 Zusammenfassung
Die wichtigsten Punkte für erfolgreiche Redis-Integration auf Coolify:
1. **Container-Name verwenden**, nicht Service-Name
2. **Protected Mode deaktivieren** mit Custom Docker Options
3. **Port 6379** verwenden, nicht 5432
4. **Environment Variables korrekt formatieren** (REDIS_HOST = nur Hostname)
5. **Test-Endpoint** erstellen zum Verifizieren
Mit dieser Konfiguration läuft Redis stabil und performant auf dem gleichen Hetzner VPS wie die Hauptanwendung, ohne zusätzliche Kosten und mit minimaler Latenz.
## 🔗 Weiterführende Dokumentation
- [Redis Best Practices](https://redis.io/docs/manual/patterns/)
- [Coolify Documentation](https://coolify.io/docs)
- [ioredis Documentation](https://github.com/redis/ioredis)
---
_Dokumentiert nach erfolgreicher Redis-Integration für uLoad auf Coolify, August 2025_

View file

@ -0,0 +1,317 @@
# Redis Cache - Local Development Setup
## Overview
Redis is used in uload to dramatically improve link redirect performance by caching frequently accessed links. This guide covers setting up Redis for local development.
## Prerequisites
- macOS with Homebrew installed
- Node.js 18+
- Running uload development environment
## Installation
### 1. Install Redis via Homebrew
```bash
# Install Redis
brew install redis
# Start Redis as a background service
brew services start redis
# Verify Redis is running
redis-cli ping
# Should return: PONG
```
### 2. Configure Environment Variables
Add the following to your `.env.development` file:
```env
# Redis Configuration (Local Development)
REDIS_HOST=localhost
REDIS_PORT=6379
# No password needed for local Redis
REDIS_PASSWORD=
```
### 3. Verify Connection
Start your development server with Redis environment variables:
```bash
# Option 1: If .env.development is loaded automatically
npm run dev
# Option 2: With explicit environment variables
REDIS_HOST=localhost REDIS_PORT=6379 npm run dev
```
Check the console output for:
```
✅ Redis: Connected successfully
```
### 4. Test Redis Status
Visit the Redis status endpoint:
```bash
curl http://localhost:5173/api/redis-status | jq
```
Expected response:
```json
{
"connected": true,
"host": "localhost",
"enabled": true,
"available": true,
"cachedLinks": 0,
"error": null
}
```
## How It Works
### Cache Flow
1. **First Visit (Cache MISS)**
```
User → Short Link → Check Redis (miss) → Query Database → Redirect → Cache Result
```
- Takes ~100-200ms
- Stores result in Redis for future requests
2. **Subsequent Visits (Cache HIT)**
```
User → Short Link → Check Redis (hit) → Redirect
```
- Takes ~10-20ms
- Skips database query entirely
### Cache Keys Structure
```
redirect:{shortCode} # Stores the target URL for quick redirects
link:{shortCode} # Stores full link object
clicks:{shortCode} # Stores click count
user:{userId}:links:page:{n} # Cached user link pages
trending:links # Sorted set of trending links
```
## Development Workflow
### 1. Monitor Redis Activity
Watch real-time Redis commands:
```bash
redis-cli monitor
```
### 2. View Cached Links
```bash
# List all cached redirects
redis-cli keys "redirect:*"
# Get specific redirect
redis-cli get "redirect:abc123"
# Check TTL (time to live)
redis-cli ttl "redirect:abc123"
```
### 3. Clear Cache
```bash
# Clear all Redis data
redis-cli flushall
# Clear specific key
redis-cli del "redirect:abc123"
```
### 4. Debug Cache Hits/Misses
Enable verbose logging in your browser console:
1. Visit a short link
2. Check browser console for:
- "Cache MISS - fetching from PocketBase"
- "Cache HIT! Redirecting from cache"
## Testing
### Run Test Suite
```bash
# Test local Redis connection
node test-local-redis.mjs
# Comprehensive cache test
node test-redis-cache.mjs
```
### Manual Testing
1. Create a short link in the app
2. Visit the link (first time = cache miss)
3. Visit again (second time = cache hit, faster)
4. Check `/api/redis-status` to see cached links count
## Configuration Options
### Cache TTL (Time To Live)
Edit `src/lib/server/linkCache.ts`:
```typescript
const CACHE_TTL = 86400; // 24 hours for popular links
const SHORT_TTL = 300; // 5 minutes for normal links
```
### Fallback Behavior
The app automatically handles Redis unavailability:
- If Redis is down, the app continues working without cache
- No errors shown to users
- Graceful degradation to database-only mode
## Troubleshooting
### Redis Won't Start
```bash
# Check if Redis is already running
ps aux | grep redis
# Check Redis service status
brew services list
# Restart Redis
brew services restart redis
# Check Redis logs
tail -f /opt/homebrew/var/log/redis.log
```
### Connection Refused
1. Verify Redis is running:
```bash
redis-cli ping
```
2. Check port availability:
```bash
lsof -i :6379
```
3. Ensure environment variables are set:
```bash
echo $REDIS_HOST
echo $REDIS_PORT
```
### Cache Not Working
1. Check Redis connection in app:
```bash
curl http://localhost:5173/api/redis-status
```
2. Verify Redis has memory available:
```bash
redis-cli info memory
```
3. Check for Redis errors in console output
### Performance Issues
1. Monitor Redis latency:
```bash
redis-cli --latency
```
2. Check Redis memory usage:
```bash
redis-cli info memory | grep used_memory_human
```
3. Clear old cache data:
```bash
redis-cli flushall
```
## Redis CLI Commands Reference
```bash
# Basic Commands
redis-cli ping # Test connection
redis-cli info # Server information
redis-cli monitor # Watch commands in real-time
redis-cli config get "*" # Show all configuration
# Key Operations
redis-cli keys "*" # List all keys (careful in production!)
redis-cli get key # Get value
redis-cli set key value # Set value
redis-cli del key # Delete key
redis-cli exists key # Check if key exists
redis-cli ttl key # Time to live in seconds
redis-cli expire key seconds # Set expiration
# Maintenance
redis-cli flushdb # Clear current database
redis-cli flushall # Clear all databases
redis-cli dbsize # Number of keys
redis-cli lastsave # Last save timestamp
# Performance
redis-cli --latency # Measure latency
redis-cli --latency-history # Latency over time
redis-cli slowlog get # Show slow queries
```
## Best Practices
1. **Don't Cache Sensitive Data**
- Password-protected links are never cached
- User-specific data has short TTLs
2. **Monitor Memory Usage**
- Redis uses in-memory storage
- Set appropriate max memory limits in production
3. **Use Appropriate TTLs**
- Short TTL for frequently changing data
- Long TTL for static content
4. **Handle Cache Invalidation**
- Clear cache when links are updated
- Implement cache warming for popular links
## Next Steps
- [Production Redis Setup](./redis-production-setup.md)
- [Cache Strategy Guide](./cache-strategy.md)
- [Performance Optimization](./performance.md)

View file

@ -0,0 +1,125 @@
# Redis Cache - Quick Start Guide
## 🚀 5-Minute Setup
### macOS/Linux
```bash
# 1. Install Redis
brew install redis
# 2. Start Redis
brew services start redis
# 3. Add to .env.development
echo "REDIS_HOST=localhost" >> .env.development
echo "REDIS_PORT=6379" >> .env.development
echo "REDIS_PASSWORD=" >> .env.development
# 4. Start app
npm run dev
# 5. Verify
curl http://localhost:5173/api/redis-status
```
### Windows (WSL2)
```bash
# 1. Install Redis in WSL2
sudo apt update
sudo apt install redis-server
# 2. Start Redis
sudo service redis-server start
# 3. Configure (same as macOS)
```
### Docker
```bash
# 1. Run Redis container
docker run -d -p 6379:6379 --name uload-redis redis:alpine
# 2. Configure (same as above)
```
## ✅ Verify It's Working
### Check Connection
```bash
# Should return: PONG
redis-cli ping
```
### Check App Status
Visit: http://localhost:5173/api/redis-status
Should see:
```json
{
"connected": true,
"available": true
}
```
### Test Cache Performance
1. Create a short link
2. Visit it (slow - cache miss)
3. Visit again (fast - cache hit!)
4. Check console for "Cache HIT!" message
## 🛠 Common Commands
```bash
# View all cached links
redis-cli keys "redirect:*"
# Clear cache
redis-cli flushall
# Monitor activity
redis-cli monitor
# Stop Redis
brew services stop redis
```
## 🔥 Quick Tips
1. **No Password Locally**: Leave REDIS_PASSWORD empty for local dev
2. **Auto-Fallback**: App works without Redis (just slower)
3. **Hot Reload**: Changes to Redis config need server restart
4. **Memory**: Redis uses ~50MB for thousands of links
## 📚 Learn More
- [Detailed Setup Guide](./redis-local-setup.md)
- [Architecture Overview](./redis-architecture.md)
- [Production Setup](./redis-production-setup.md)
## 🆘 Help
**Redis won't start?**
```bash
brew services restart redis
```
**Connection refused?**
```bash
# Check if running
ps aux | grep redis
```
**Cache not working?**
- Check console for Redis connection message
- Verify environment variables are loaded
- Try explicit env vars: `REDIS_HOST=localhost npm run dev`