API Rate Limiting – ograniczanie zapytań w 2026

08 lutego 202611 min czytaniaURL: /pl/blog/api-rate-limiting-ograniczanie-zapytan-2026
Autor: DevStudio.itStudio Web & AI

Czym jest Rate Limiting? Jak działa, strategie, implementacja w Node.js, Express, Next.js, Redis i best practices dla bezpiecznych API.

rate limitingapi securityddos protectionredisexpressnextjsapi best practices

TL;DR

Rate Limiting to ograniczanie liczby zapytań do API w określonym czasie. Chroni przed nadużyciami, DDoS i zapewnia sprawiedliwy dostęp do zasobów. Oto jak wdrożyć rate limiting w 2026.

Dla kogo to jest

  • Deweloperów budujących publiczne API
  • Zespołów potrzebujących ochrony przed nadużyciami
  • Firm oferujących API jako produkt
  • Projektów wymagających kontroli kosztów

Fraza (SEO)

rate limiting, api rate limit, ddos protection, api security, throttling, express rate limit, redis rate limiting

Czym jest Rate Limiting?

Rate Limiting to:

  • Ograniczenie liczby zapytań w czasie
  • Ochrona przed nadużyciami i DDoS
  • Sprawiedliwy dostęp do zasobów
  • Kontrola kosztów infrastruktury

Przykład:

Limit: 100 zapytań na minutę
Użytkownik 1: 50 zapytań ✅
Użytkownik 2: 150 zapytań ❌ (blokada po 100)

Dlaczego Rate Limiting?

1. Ochrona przed nadużyciami

Scenariusze:

  • Bot scraping danych
  • Brute force attacks
  • API abuse
  • Nieautoryzowany dostęp

Bez rate limiting:

Atakujący: 10,000 zapytań/sekundę
Serwer: Przeciążony, crash

Z rate limiting:

Atakujący: 10,000 zapytań/sekundę
Rate limiter: Blokuje po 100/min
Serwer: Działa normalnie

2. Kontrola kosztów

Problem:

  • Każde zapytanie kosztuje (compute, database)
  • Nieograniczone API = nieograniczone koszty
  • Trudna kontrola budżetu

Rozwiązanie:

  • Limity per użytkownik
  • Kontrola zużycia zasobów
  • Przewidywalne koszty

3. Sprawiedliwy dostęp

Dla wszystkich użytkowników:

  • Jeden użytkownik nie może zmonopolizować API
  • Równy dostęp do zasobów
  • Lepsze doświadczenie

4. Zapobieganie błędom

Ochrona przed:

  • Przypadkowym infinite loop
  • Błędami w kodzie klienta
  • Niewłaściwym użyciem API

Strategie Rate Limiting

1. Fixed Window

Jak działa:

  • Okno czasowe (np. 1 minuta)
  • Licznik resetuje się co okno
  • Proste w implementacji

Przykład:

Okno: 1 minuta
Limit: 100 zapytań
00:00-00:59: 100 zapytań ✅
01:00-01:59: Reset, nowe 100 zapytań ✅

Problem:

  • Burst na granicy okien
  • Możliwość 200 zapytań w 2 sekundy (na końcu i początku okna)

2. Sliding Window

Jak działa:

  • Okno przesuwające się w czasie
  • Liczy zapytania z ostatnich N sekund
  • Bardziej sprawiedliwe

Przykład:

Limit: 100 zapytań na 60 sekund
00:00: 50 zapytań (dostępne: 50)
00:30: 30 zapytań (dostępne: 20)
01:00: 20 zapytań (dostępne: 0, blokada)
01:30: Zapytania z 00:30 wygasają (dostępne: 20)

3. Token Bucket

Jak działa:

  • Wiadro z tokenami
  • Tokeny dodawane w stałym tempie
  • Zapytanie zużywa token
  • Brak tokenów = blokada

Przykład:

Pojemność: 100 tokenów
Dodawanie: 10 tokenów/sekundę
Zapytanie: 1 token

4. Leaky Bucket

Jak działa:

  • Wiadro z dziurą
  • Zapytania wchodzą do wiadra
  • Stałe tempo wyciekania
  • Pełne wiadro = blokada

Implementacja

1. Express.js z express-rate-limit

Instalacja:

npm install express-rate-limit

Podstawowe użycie:

import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minut
  max: 100, // 100 zapytań na okno
  message: 'Too many requests, please try again later.',
  standardHeaders: true,
  legacyHeaders: false,
});

app.use('/api/', limiter);

Różne limity dla różnych endpointów:

// Ogólny limit
const generalLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100,
});

// Stricter limit dla auth
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5, // Tylko 5 prób logowania
  skipSuccessfulRequests: true,
});

app.use('/api/', generalLimiter);
app.use('/api/auth/login', authLimiter);

Z Redis (dla wielu instancji):

npm install express-rate-limit redis
import RedisStore from 'rate-limit-redis';
import { createClient } from 'redis';

const redisClient = createClient();
await redisClient.connect();

const limiter = rateLimit({
  store: new RedisStore({
    client: redisClient,
    prefix: 'rl:',
  }),
  windowMs: 15 * 60 * 1000,
  max: 100,
});

2. Next.js API Routes

Middleware approach:

// lib/rateLimit.ts
import { NextRequest, NextResponse } from 'next/server';
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';

const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL!,
  token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});

const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(10, '10 s'),
});

export async function rateLimit(request: NextRequest) {
  const ip = request.ip ?? '127.0.0.1';
  const { success, limit, remaining } = await ratelimit.limit(ip);
  
  if (!success) {
    return NextResponse.json(
      { error: 'Too many requests' },
      { status: 429 }
    );
  }
  
  return { limit, remaining };
}

Użycie w API route:

// app/api/users/route.ts
import { rateLimit } from '@/lib/rateLimit';

export async function GET(request: NextRequest) {
  const rateLimitResult = await rateLimit(request);
  
  if (rateLimitResult instanceof NextResponse) {
    return rateLimitResult; // Rate limit exceeded
  }
  
  // Normalna logika
  return NextResponse.json({ users: [] });
}

3. Custom implementation z Redis

Sliding window log:

import { createClient } from 'redis';

const redis = createClient();
await redis.connect();

async function checkRateLimit(
  key: string,
  limit: number,
  windowSeconds: number
): Promise<{ allowed: boolean; remaining: number }> {
  const now = Date.now();
  const windowStart = now - windowSeconds * 1000;
  
  // Usuń stare zapytania
  await redis.zRemRangeByScore(key, 0, windowStart);
  
  // Policz aktualne zapytania
  const count = await redis.zCard(key);
  
  if (count >= limit) {
    return { allowed: false, remaining: 0 };
  }
  
  // Dodaj nowe zapytanie
  await redis.zAdd(key, {
    score: now,
    value: `${now}-${Math.random()}`,
  });
  
  // Ustaw TTL
  await redis.expire(key, windowSeconds);
  
  return { allowed: true, remaining: limit - count - 1 };
}

// Użycie
const result = await checkRateLimit('user:123', 100, 60);
if (!result.allowed) {
  return res.status(429).json({ error: 'Rate limit exceeded' });
}

Best Practices

1. Różne limity dla różnych endpointów

Strategia:

const limits = {
  public: { windowMs: 15 * 60 * 1000, max: 100 },
  auth: { windowMs: 15 * 60 * 1000, max: 5 },
  upload: { windowMs: 60 * 60 * 1000, max: 10 },
  search: { windowMs: 60 * 1000, max: 20 },
};

2. Identyfikacja użytkowników

Metody:

  • IP address (dla publicznych API)
  • API key (dla autoryzowanych)
  • User ID (dla zalogowanych)
  • Session ID

Przykład:

function getIdentifier(req: Request): string {
  // Priorytet: API key > User ID > IP
  return (
    req.headers.get('x-api-key') ||
    req.user?.id ||
    req.ip ||
    'anonymous'
  );
}

3. Headers informacyjne

Standardowe headery:

res.setHeader('X-RateLimit-Limit', '100');
res.setHeader('X-RateLimit-Remaining', '50');
res.setHeader('X-RateLimit-Reset', resetTime);

4. Graceful degradation

Zamiast blokować całkowicie:

if (rateLimitExceeded) {
  // Opcja 1: Queue request
  await queueRequest(request);
  
  // Opcja 2: Throttle (spowolnij)
  await sleep(1000);
  
  // Opcja 3: Return cached data
  return getCachedResponse();
}

5. Monitoring i alerty

Śledź:

  • Liczbę zablokowanych zapytań
  • Top użytkowników/IP
  • Wzorce nadużyć
  • Performance impact

Rate Limiting vs Throttling

Rate Limiting Throttling
Blokuje po limicie Spowalnia zapytania
Hard limit Soft limit
429 status Opóźnia odpowiedź
Dla bezpieczeństwa Dla wydajności

FAQ

Jakie limity ustawić?

Zależy od przypadku:

  • Publiczne API: 100-1000/min
  • Auth endpoints: 5-10/min
  • Upload: 10-50/godzinę
  • Search: 20-100/min

Co zrobić gdy limit przekroczony?

  • Zwróć 429 status
  • Dodaj Retry-After header
  • Poinformuj użytkownika
  • Zaoferuj upgrade planu

Czy rate limiting spowalnia API?

Minimalnie (zwykle <1ms). Warto użyć Redis dla cache i szybkiego sprawdzania.

Jak testować rate limiting?

// Test
for (let i = 0; i < 150; i++) {
  const res = await fetch('/api/endpoint');
  if (i >= 100) {
    expect(res.status).toBe(429);
  }
}

Chcesz wdrożyć Rate Limiting w swoim API?

O autorze

Budujemy szybkie strony WWW, aplikacje web/mobile, chatboty AI i hosting — z naciskiem na SEO i konwersję.

Przydatne linki (polecamy)

Jeśli chcesz przejść od wiedzy do wdrożenia — tu masz skróty do naszych rozwiązań, hostingu i realizacji.

Chcesz wdrożenie pod SEO i konwersję?

Zróbmy to szybko: zakres + wycena + terminy.

Wyceń projekt