# ORIGIN_PERFORMANCE_TARGETS.md
## đ RĂSUMĂ EXĂCUTIF
Ce document définit les objectifs de performance mesurables et réalistes pour tous les composants de la plateforme Veza. Il spécifie targets précis pour latence API (p95 < 100ms, p99 < 200ms), database (p95 < 10ms), frontend (Lighthouse Performance ℠90, Accessibility ℠95), audio streaming (start < 500ms, rebuffering < 0.5%), avec monitoring (Prometheus), plan de mesure (Lighthouse CI, k6, pg_stat_statements), et optimization strategies garantissant expérience utilisateur fluide et scalabilité production.
## đŻ OBJECTIFS
### Objectif Principal
Garantir performance optimale avec latence API < 100ms (p95), temps chargement < 2s, zero buffering audio/vidéo, et scalabilité jusqu'à 100K utilisateurs concurrents avec dégradation gracieuse.
### Objectifs Secondaires
- Optimiser ressources (CPU < 70%, RAM < 80%)
- Réduire coûts infrastructure (efficient resource utilization)
- Détecter régressions performance automatiquement (CI/CD)
- Fournir expérience utilisateur fluide (no jank, 60 FPS)
## đ TABLE DES MATIĂRES
1. [Performance Philosophy](#1-performance-philosophy)
2. [Backend Performance Targets](#2-backend-performance-targets)
3. [Frontend Performance Targets](#3-frontend-performance-targets)
4. [Database Performance Targets](#4-database-performance-targets)
5. [Network Performance Targets](#5-network-performance-targets)
6. [Audio Streaming Performance](#6-audio-streaming-performance)
7. [Monitoring & Alerting](#7-monitoring--alerting)
8. [Performance Testing](#8-performance-testing)
9. [Optimization Strategies](#9-optimization-strategies)
10. [Performance Budgets](#10-performance-budgets)
## đ RĂGLES IMMUABLES
1. **API Latency**: p95 < 100ms, p99 < 200ms - CI/CD bloque si dépassé
2. **Database Queries**: p95 < 10ms - N+1 queries interdites
3. **Frontend Load**: First Contentful Paint < 1.5s, Time to Interactive < 3.5s
4. **Bundle Size**: Initial JS bundle < 200KB gzipped
5. **Memory Leaks**: Zero memory leaks tolérés (CI/CD checks)
6. **Audio Streaming**: Rebuffering < 0.5%, stream start < 500ms
7. **Throughput**: Min 10K req/s sustained (backend)
8. **Resource Usage**: CPU < 70%, Memory < 80% (average)
9. **Cache Hit Rate**: > 90% for frequently accessed data
10. **Mobile Performance**: Lighthouse Performance score â„ 90
## 1. PERFORMANCE PHILOSOPHY
### 1.1 Performance Principles
**User-Centric Performance**:
- **Perceived Performance > Actual Performance**: Users care about what they experience
- **Critical Rendering Path**: Optimize what users see first
- **Progressive Enhancement**: Core functionality works fast, enhancements load progressively
**Performance Metrics Hierarchy**:
```
1. Core Web Vitals (Google)
- LCP (Largest Contentful Paint) < 2.5s
- FID (First Input Delay) < 100ms
- CLS (Cumulative Layout Shift) < 0.1
2. Custom Business Metrics
- Time to First Track Play < 3s
- Search Results < 500ms
- Upload Progress Feedback < 100ms
```
### 1.2 Performance SLOs (Service Level Objectives)
| Metric | Target | Stretch Goal |
|--------|--------|--------------|
| **API Response Time (p95)** | < 100ms | < 50ms |
| **API Response Time (p99)** | < 200ms | < 100ms |
| **Database Query (p95)** | < 10ms | < 5ms |
| **Frontend Load (FCP)** | < 1.5s | < 1s |
| **Frontend Load (TTI)** | < 3.5s | < 2s |
| **Audio Stream Start** | < 500ms | < 300ms |
| **Search Results** | < 500ms | < 200ms |
| **Uptime** | 99.9% | 99.99% |
## 2. BACKEND PERFORMANCE TARGETS
### 2.1 API Response Times
**Endpoints Performance Targets**:
| Endpoint Category | p50 | p95 | p99 | Examples |
|-------------------|-----|-----|-----|----------|
| **Simple Reads** | < 20ms | < 50ms | < 100ms | GET /users/{id}, GET /tracks/{id} |
| **Complex Reads** | < 50ms | < 100ms | < 200ms | GET /tracks (with filters), GET /search |
| **Writes** | < 50ms | < 150ms | < 300ms | POST /users, PUT /tracks/{id} |
| **File Uploads** | < 2s | < 5s | < 10s | POST /tracks (upload) |
| **Aggregations** | < 100ms | < 300ms | < 500ms | GET /analytics/dashboard |
**Critical Endpoints** (Strict Targets):
- `GET /tracks/{id}`: p95 < 30ms
- `POST /tracks/{id}/play`: p95 < 20ms
- `GET /search?q=`: p95 < 200ms
- `POST /auth/login`: p95 < 100ms
- `GET /feed`: p95 < 150ms
### 2.2 Throughput Targets
| Endpoint | Target RPS | Peak RPS | Concurrent Users |
|----------|------------|----------|------------------|
| **GET /tracks** | 5,000 | 10,000 | 50,000 |
| **POST /tracks/{id}/play** | 10,000 | 20,000 | 100,000 |
| **GET /search** | 2,000 | 5,000 | 20,000 |
| **POST /auth/login** | 500 | 1,000 | 5,000 |
| **WebSocket connections** | 10,000 | 20,000 | 20,000 |
### 2.3 Resource Utilization
**Per Service Limits**:
```yaml
backend-api:
cpu_usage: < 70% (average), < 90% (peak)
memory_usage: < 80% (average), < 95% (peak)
goroutines: < 10,000
database_connections: < 100 (per instance)
chat-server:
cpu_usage: < 60%
memory_usage: < 70%
websocket_connections: < 10,000 (per instance)
message_throughput: > 50,000 msg/s
stream-server:
cpu_usage: < 80% (audio processing intensive)
memory_usage: < 75%
concurrent_streams: > 5,000
bandwidth: > 10 Gbps
```
### 2.4 Error Rates
| Error Type | Target | Alert Threshold |
|------------|--------|-----------------|
| **4xx Errors** | < 1% | > 2% |
| **5xx Errors** | < 0.1% | > 0.5% |
| **Timeouts** | < 0.01% | > 0.1% |
| **Database Errors** | < 0.01% | > 0.05% |
## 3. FRONTEND PERFORMANCE TARGETS
### 3.1 Core Web Vitals
**Lighthouse Scores** :
- **Performance**: â„ 90
- **Accessibility**: â„ 95
- **Best Practices**: â„ 90
- **SEO**: â„ 90
**Detailed Metrics**:
| Metric | Good | Needs Improvement | Poor | Target |
|--------|------|-------------------|------|--------|
| **LCP (Largest Contentful Paint)** | †2.5s | 2.5s - 4.0s | > 4.0s | **< 2s** |
| **FID (First Input Delay)** | †100ms | 100ms - 300ms | > 300ms | **< 50ms** |
| **CLS (Cumulative Layout Shift)** | †0.1 | 0.1 - 0.25 | > 0.25 | **< 0.05** |
| **FCP (First Contentful Paint)** | †1.8s | 1.8s - 3.0s | > 3.0s | **< 1.5s** |
| **TTI (Time to Interactive)** | †3.8s | 3.8s - 7.3s | > 7.3s | **< 3.5s** |
| **TBT (Total Blocking Time)** | †200ms | 200ms - 600ms | > 600ms | **< 150ms** |
| **Speed Index** | †3.4s | 3.4s - 5.8s | > 5.8s | **< 3s** |
### 3.2 Bundle Size
**JavaScript Bundles**:
```
Initial Bundle (gzipped):
âââ vendor.js (React, Router, etc.): < 150 KB
âââ main.js (App code): < 50 KB
âââ TOTAL: < 200 KB
Lazy-Loaded Bundles:
âââ dashboard.js: < 30 KB
âââ player.js: < 40 KB
âââ upload.js: < 25 KB
âââ admin.js: < 50 KB
CSS:
âââ main.css (Tailwind): < 20 KB (purged)
âââ fonts: < 50 KB (subset)
```
**Image Optimization**:
- **Hero Images**: < 100 KB (WebP)
- **Thumbnails**: < 20 KB (WebP)
- **Avatars**: < 10 KB (WebP)
- **Icons**: Inline SVG or sprite sheet < 5 KB
### 3.3 Runtime Performance
**Frame Rate**:
- **Animations**: 60 FPS (16.67ms per frame)
- **Scrolling**: Smooth (no jank)
- **Interactions**: < 100ms response time
**Memory Usage**:
- **Initial Load**: < 50 MB
- **Peak Usage**: < 150 MB
- **Memory Leaks**: Zero (CI/CD checks)
### 3.4 Mobile Performance
**Mobile-Specific Targets** (4G connection):
- **FCP**: < 2.5s
- **TTI**: < 5s
- **Bundle Size**: < 150 KB initial
- **Lighthouse Performance**: â„ 90
## 4. DATABASE PERFORMANCE TARGETS
### 4.1 Query Performance
**Query Latency Targets**:
| Query Type | p50 | p95 | p99 | Examples |
|------------|-----|-----|-----|----------|
| **Simple SELECT** | < 2ms | < 5ms | < 10ms | SELECT * FROM users WHERE id = ? |
| **JOIN (2 tables)** | < 5ms | < 10ms | < 20ms | Users JOIN Tracks |
| **JOIN (3+ tables)** | < 10ms | < 20ms | < 50ms | Complex queries |
| **Aggregations** | < 10ms | < 30ms | < 100ms | COUNT, SUM, AVG |
| **Full-Text Search** | < 20ms | < 50ms | < 100ms | GIN index searches |
| **INSERT** | < 3ms | < 10ms | < 20ms | Single row insert |
| **UPDATE** | < 5ms | < 15ms | < 30ms | Single row update |
**Slow Query Threshold**: > 100ms (logged and investigated)
### 4.2 Connection Pool
**PgBouncer Configuration**:
```ini
[pgbouncer]
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 25
min_pool_size = 10
reserve_pool_size = 5
max_db_connections = 100
# Performance
query_timeout = 30
idle_transaction_timeout = 60
```
**Metrics Targets**:
- **Connection Utilization**: < 80%
- **Wait Time**: < 10ms
- **Connection Errors**: < 0.01%
### 4.3 Index Performance
**Index Requirements**:
- **Index Hit Rate**: > 99%
- **Sequential Scans on Large Tables**: Zero (always use indexes)
- **Index Size**: < 20% of table size
**Monitoring Queries**:
```sql
-- Index usage
SELECT schemaname, tablename, indexname, idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan < 100
ORDER BY idx_scan;
-- Missing indexes (high seq scans)
SELECT schemaname, tablename, seq_scan, seq_tup_read
FROM pg_stat_user_tables
WHERE seq_scan > 1000
ORDER BY seq_tup_read DESC;
```
### 4.4 Cache Hit Ratio
**PostgreSQL Cache**:
- **Shared Buffers Hit Rate**: > 95%
- **Index Hit Rate**: > 99%
**Application Cache (Redis)**:
- **Hit Rate**: > 90%
- **Latency**: < 1ms (p95)
- **Eviction Rate**: < 5%
## 5. NETWORK PERFORMANCE TARGETS
### 5.1 API Response Sizes
**Payload Sizes**:
```
Endpoints:
GET /users/{id}: < 2 KB
GET /tracks: < 50 KB (20 items)
GET /tracks/{id}: < 5 KB
GET /search: < 100 KB (50 results)
GET /feed: < 200 KB (100 items)
Images (served via CDN):
Thumbnail (200x200): < 20 KB (WebP)
Cover (800x800): < 100 KB (WebP)
Banner (1920x400): < 150 KB (WebP)
```
### 5.2 CDN Performance
**CDN Metrics**:
- **Cache Hit Ratio**: > 95%
- **Latency (p95)**: < 50ms
- **Bandwidth**: > 10 Gbps
- **Geographic Coverage**: < 100ms from any location
**CDN Configuration**:
```nginx
# Cache headers
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location /api/ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
```
### 5.3 Compression
**Gzip/Brotli Compression**:
- **Text (HTML, CSS, JS, JSON)**: Enabled (Brotli level 6)
- **Images**: Pre-compressed (WebP, AVIF)
- **Audio**: No compression (already compressed)
**Compression Ratios**:
- **JS/CSS**: 70-80% reduction
- **JSON**: 60-70% reduction
- **HTML**: 50-60% reduction
## 6. AUDIO STREAMING PERFORMANCE
### 6.1 Streaming Latency
**Latency Targets**:
- **Stream Start**: < 500ms (target: 300ms)
- **Buffer Fill**: < 200ms
- **Seek Time**: < 100ms
- **Quality Switch**: < 50ms (adaptive bitrate)
**Buffering**:
- **Initial Buffer**: 2 seconds
- **Rebuffering rate**: < 0.5% des sessions de lecture
- **Rebuffering Events**: < 0.5% of plays
### 6.2 Audio Quality
**Adaptive Bitrate Streaming**:
```
Network Speed â Bitrate:
< 500 kbps: 64 kbps (low quality)
500 kbps - 1 Mbps: 128 kbps (medium quality)
1 Mbps - 5 Mbps: 256 kbps (high quality)
> 5 Mbps: 320 kbps (premium quality)
```
**Format Support**:
- **Lossy**: MP3 (320 kbps), AAC (256 kbps), Opus (128 kbps)
- **Lossless**: FLAC (16-bit/44.1kHz)
### 6.3 Concurrent Streams
**Capacity Targets**:
- **Per Server**: 5,000 concurrent streams
- **Total Capacity**: 100,000 concurrent streams (20 servers)
- **Bandwidth**: 10 Gbps per server (avg 256 kbps/stream)
## 7. MONITORING & ALERTING
### 7.1 Prometheus Metrics
**RED Metrics** (Rate, Errors, Duration):
```promql
# Request Rate
rate(http_requests_total[5m])
# Error Rate
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m])
# Duration (Latency)
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
```
**USE Metrics** (Utilization, Saturation, Errors):
```promql
# CPU Utilization
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Memory Utilization
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100
# Disk Saturation
rate(node_disk_io_time_seconds_total[5m])
```
### 7.2 Alerting Rules
**Critical Alerts** (PagerDuty):
```yaml
groups:
- name: critical_alerts
interval: 30s
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.01
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate detected ({{ $value }}%)"
- alert: HighLatency
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "API latency p95 > 100ms ({{ $value }}s)"
- alert: DatabaseDown
expr: up{job="postgres"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "PostgreSQL is down"
```
**Warning Alerts** (Slack):
```yaml
- alert: ModerateCPUUsage
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 70
for: 10m
labels:
severity: warning
annotations:
summary: "CPU usage > 70% for 10 minutes"
- alert: SlowQueries
expr: rate(postgres_slow_queries_total[5m]) > 10
for: 5m
labels:
severity: warning
annotations:
summary: "High number of slow queries (> 10/min)"
```
### 7.3 Grafana Dashboards
**Dashboard 1: API Performance**
- Request rate (RPS)
- Latency (p50, p95, p99)
- Error rate (4xx, 5xx)
- Throughput (MB/s)
- Active connections
**Dashboard 2: Database Performance**
- Query latency (p95, p99)
- Connection pool usage
- Cache hit ratio
- Slow queries (> 100ms)
- Replication lag
**Dashboard 3: Frontend Performance**
- Lighthouse scores (from CI/CD)
- Core Web Vitals (LCP, FID, CLS)
- Bundle sizes
- Resource loading times
- Error tracking (Sentry)
## 8. PERFORMANCE TESTING
### 8.1 Benchmarking
**Go Benchmarks**:
```go
func BenchmarkGetUserByID(b *testing.B) {
repo := setupRepo()
user := createTestUser(repo)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := repo.GetByID(user.ID)
if err != nil {
b.Fatal(err)
}
}
}
// Target: < 100,000 ns/op (0.1ms)
// BenchmarkGetUserByID-8 50000 25000 ns/op 1024 B/op 15 allocs/op
```
**Rust Benchmarks**:
```rust
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn bench_get_user(c: &mut Criterion) {
let repo = setup_repo();
let user_id = create_test_user(&repo);
c.bench_function("get_user_by_id", |b| {
b.iter(|| {
repo.get_by_id(black_box(&user_id))
});
});
}
// Target: < 100ÎŒs
criterion_group!(benches, bench_get_user);
criterion_main!(benches);
```
### 8.2 Load Testing (k6)
**Continuous Load Test**:
```javascript
// k6-continuous.js
import http from 'k6/http';
import { check } from 'k6';
export const options = {
stages: [
{ duration: '5m', target: 1000 },
{ duration: '10m', target: 1000 },
{ duration: '5m', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<100', 'p(99)<200'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
const res = http.get('https://api.veza.app/v1/tracks');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 100ms': (r) => r.timings.duration < 100,
});
}
```
### 8.3 Performance Regression Detection
**CI/CD Integration**:
```yaml
# .github/workflows/performance.yml
name: Performance Tests
on: [push, pull_request]
jobs:
benchmark:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Go benchmarks
run: |
cd veza-backend-api
go test -bench=. -benchmem > bench-new.txt
- name: Compare with baseline
run: |
benchstat bench-baseline.txt bench-new.txt
# Fail if regression > 10%
- name: Update baseline (if main branch)
if: github.ref == 'refs/heads/main'
run: cp bench-new.txt bench-baseline.txt
```
### 8.4 Plan de Mesure en Production
**Prometheus** (métriques actives en production) :
```yaml
monitoring:
prometheus:
status: actif en production
scrape_interval: 15s
retention: 30 jours
métriques:
- http_request_duration_seconds (histogram, par endpoint)
- http_requests_total (counter, par status code)
- audio_stream_start_duration_seconds (histogram)
- audio_rebuffering_events_total (counter)
- db_query_duration_seconds (histogram)
- active_connections (gauge)
```
**Lighthouse CI** (GitHub Actions, bloquant) :
```yaml
lighthouse_ci:
déclencheur: chaque PR + chaque merge sur main
urls_testées:
- / (landing)
- /dashboard
- /tracks/{id}
- /upload
seuils_bloquants:
performance: 90
accessibility: 95
action: gh-actions (lhci autorun)
rapport: commentaire automatique sur PR
```
**k6 Load Tests** (CD nightly) :
```yaml
k6_load_tests:
fréquence: nightly (CD pipeline, 02:00 UTC)
scénarios:
- smoke: 10 VUs, 1 min (sanity check)
- load: 500 VUs, 10 min (charge normale)
- stress: 2000 VUs, 5 min (pic de charge)
seuils:
http_req_duration_p95: < 100ms
http_req_duration_p99: < 200ms
http_req_failed: < 1%
rapport: Grafana dashboard + Slack notification si échec
```
**pg_stat_statements** (activé en production) :
```yaml
pg_stat_statements:
status: activé
paramĂštres:
pg_stat_statements.max: 10000
pg_stat_statements.track: all
monitoring:
- requĂȘtes > 10ms p95 signalĂ©es automatiquement
- top 20 requĂȘtes par temps cumulĂ© (dashboard Grafana)
- reset hebdomadaire des statistiques
alerte: requĂȘte > 100ms exĂ©cutĂ©e > 100 fois/min â Slack
```
## 9. OPTIMIZATION STRATEGIES
### 9.1 Backend Optimizations
**Database Query Optimization**:
```go
// â BAD - N+1 query problem
func GetUsersWithTracks() ([]User, error) {
var users []User
db.Find(&users)
for i := range users {
db.Model(&users[i]).Association("Tracks").Find(&users[i].Tracks) // N queries
}
return users, nil
}
// â
GOOD - Single query with eager loading
func GetUsersWithTracks() ([]User, error) {
var users []User
err := db.Preload("Tracks").Find(&users).Error // 2 queries total
return users, err
}
```
**Caching Strategy**:
```go
// Cache frequently accessed data
func (s *TrackService) GetTrack(id string) (*Track, error) {
// Try cache first
cacheKey := fmt.Sprintf("track:%s", id)
if cached, err := s.cache.Get(cacheKey); err == nil {
var track Track
json.Unmarshal([]byte(cached), &track)
return &track, nil
}
// Cache miss - fetch from database
track, err := s.repo.GetByID(id)
if err != nil {
return nil, err
}
// Store in cache (1 hour TTL)
data, _ := json.Marshal(track)
s.cache.Set(cacheKey, string(data), 1*time.Hour)
return track, nil
}
```
### 9.2 Frontend Optimizations
**Code Splitting**:
```typescript
// Lazy load routes
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Upload = lazy(() => import('./pages/Upload'));
const Profile = lazy(() => import('./pages/Profile'));
function App() {
return (
```
**Memoization**:
```typescript
// Memoize expensive calculations
const expensiveValue = useMemo(() => {
return tracks.filter(/* complex filter */).sort(/* expensive sort */);
}, [tracks]); // Only recalculate when tracks change
// Memoize components
const TrackItem = memo(({ track }: { track: Track }) => {
return