v2.5APIs & Backend

Rate Limiting

Schütze deine API vor Missbrauch und Überlastung mit hocheffizientem, deklarativem Rate Limiting.

@RateLimit Decorator

Der einfachste Weg, einen Endpunkt zu limitieren. Velisch optimiert Rate Limiting direkt im Compiler.

@POST("/api/generate")
@RateLimit(requests: 10, window: "1m")
fn generateContent(prompt: string): string {
    // Dieser Endpunkt ist auf 10 Anfragen pro Minute limitiert
    return ai.generate(prompt);
}

@GET("/api/search")
@RateLimit(requests: 100, window: "1h")
fn search(query: string): List<Result> {
    return db.search(query);
}

Dynamische Limits

Definiere Limits basierend auf Benutzerrollen, Subscription-Tier oder API-Schlüsseln:

fn getLimit(user: User): number {
    match user.tier {
        "free" => 100,
        "pro" => 1000,
        "enterprise" => 10000,
        _ => 50
    }
}

@Auth
@GET("/api/data")
@RateLimit(requests: getLimit, window: "1h")
fn getData(): Data {
    return db.fetch();
}

// Oder mit direkter Tier-Annotation
@Auth
@GET("/api/premium")
@RateLimit(tier: "pro", requests: 500, window: "1h")
@RateLimit(tier: "enterprise", requests: 5000, window: "1h")
fn getPremiumData(): Data {
    return fetchPremiumData();
}

Rate Limit Strategien

Per User
@RateLimit(
    requests: 100, 
    window: "1h",
    by: "user"  // Default
)
fn userEndpoint(): Data { ... }
Per IP
@RateLimit(
    requests: 50, 
    window: "1m",
    by: "ip"
)
fn publicEndpoint(): Data { ... }
Global
@RateLimit(
    requests: 1000, 
    window: "1s",
    by: "global"
)
fn heavyEndpoint(): Data { ... }
Per API Key
@ApiKey
@RateLimit(
    requests: 500, 
    window: "1h",
    by: "apikey"
)
fn apiEndpoint(): Data { ... }

Sliding Window vs Fixed Window

// Fixed Window (Standard)
// Zähler wird am Ende jedes Fensters zurückgesetzt
@RateLimit(requests: 100, window: "1h", algorithm: "fixed")
fn fixedWindowEndpoint(): Data { ... }

// Sliding Window
// Gleitender Durchschnitt, gleichmäßigere Verteilung
@RateLimit(requests: 100, window: "1h", algorithm: "sliding")
fn slidingWindowEndpoint(): Data { ... }

// Token Bucket
// Erlaubt kurze Bursts, ideal für variable Workloads
@RateLimit(requests: 100, window: "1h", algorithm: "token_bucket", burst: 20)
fn burstableEndpoint(): Data { ... }

Response Headers

Velisch fügt automatisch Rate-Limit-Headers zur Response hinzu:

HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
Retry-After: 3600  (nur bei 429)

429 Too Many Requests

{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Please try again in 3600 seconds.",
  "retryAfter": 3600
}

Globale Konfiguration

// In config.velin oder main.velin
app.rateLimit({
    defaultLimit: 100,
    defaultWindow: "1h",
    algorithm: "sliding",
    
    // Redis für verteilte Rate Limits
    store: "redis",
    redisUrl: config.get("REDIS_URL"),
    
    // Whitelist für interne Services
    whitelist: [
        "10.0.0.0/8",
        "192.168.0.0/16",
    ],
    
    // Custom Handler für 429
    onLimitExceeded: |req, res| {
        log.warn("Rate limit exceeded for " + req.ip);
        res.status(429).json({
            error: "Zu viele Anfragen",
            retryAfter: res.headers["Retry-After"],
        });
    }
});

Best Practices

Sensible Defaults

Setze globale Limits als Baseline

Tier-basierte Limits

Unterschiedliche Limits für verschiedene Subscription-Tiers

Monitoring

Überwache Rate-Limit-Hits für Capacity Planning

Graceful Degradation

Gib hilfreiche Retry-After Header zurück