Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

API Rate Limiting'i IP, Kullanıcı ve Endpoint Bazlı Nasıl Granüler Hale Getirdim?

codrix

Üye
Katılım
14 Mart 2026
Mesajlar
30
Merhaba arkadaşlar, bugün başımı çok ağrıtan bir konudan bahsedeceğim. Bir API projesinde, klasik IP bazlı rate limiting çözümleri artık yeterli gelmiyordu. Kötü niyetli bir kullanıcı, tüm endpoint'lerimize aynı limit içinde saldırı yapabiliyor veya premium bir kullanıcı ile ücretsiz kullanıcıyı aynı kefeye koymak adil olmuyordu. İşte bu sorunu nasıl katman katman çözüme kavuşturduğumu anlatacağım.

🔥 Klasik Çözüm Neden Yetmedi?

Geleneksel olarak, bir middleware ile sadece IP adresini kontrol ediyorduk. Kodu aşağıda paylaşıyorum:

JavaScript:
const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
    windowMs: 15  60  1000, // 15 dakika
    max: 100, // IP başına 100 istek
    message: 'Çok fazla istek gönderdiniz, lütfen 15 dakika sonra tekrar deneyin.'
});
app.use('/api', limiter);

Bu kod, her şeyi güzelce sınırlıyordu ama /api/profile endpoint'ine yapılan zararsız isteklerle, /api/checkout gibi kritik endpoint'lere yapılan istekler aynı limitten tüketiyordu. Ayrıca, giriş yapmış bir kullanıcı ile anonim bir ziyaretçi de aynı muameleyi görüyordu. Bu adaletsizlik beni rahatsız etti!

🧠 Çok Katmanlı (Multi-Layer) Stratejim

Çözüm olarak, rate limiting mantığını üç katmana ayırmaya karar verdim:
1. Global IP Limiti: Sunucuyu korumak için en temel kalkan.
2. Kullanıcı Bazlı Limit: Kimlik doğrulaması yapılmış kullanıcılar için, planlarına (ücretsiz, premium, admin) göre esnek limitler.
3. Endpoint Bazlı Limit: Her bir API yolunun kritik seviyesine göre özel limitler.

Bu yaklaşım için express-rate-limit ve redis kullanarak merkezi bir sayaç yönetimi kurdum.

⚙️ Redis ile Esnek Limit Yönetimi

Öncelikle, kullanıcı tiplerine ve endpoint'lere göre limit kurallarımızı bir konfigürasyon objesinde tanımladım.

JavaScript:
const rateLimitRules = {
    // Kullanıcı Tiplerine Göre Global Dakikalık Limitler
    userTier: {
        anonymous: { windowMs: 60000, max: 60 }, // Dakikada 60 istek
        free: { windowMs: 60000, max: 120 },
        premium: { windowMs: 60000, max: 300 },
        admin: { windowMs: 60000, max: 1000 }
    },
    // Endpoint'lere Özel Ek Limitler (Kullanıcı limitine EK olarak uygulanır)
    endpoints: {
        '/api/auth/login': { windowMs: 300000, max: 5 }, // 5 dakikada 5 başarısız giriş
        '/api/checkout': { windowMs: 3600000, max: 10 }, // Saatte 10 satın alma
        '/api/search': { windowMs: 10000, max: 30 } // 10 saniyede 30 arama
    }
};

🔐 Akıllı Middleware'im

Sonrasında, gelen her isteği analiz edip, ona uygun limit kurallarını dinamik olarak uygulayan bir middleware yazdım. Burada sihir, generateKey fonksiyonunda.

JavaScript:
const Redis = require('ioredis');
const redisClient = new Redis(process.env.REDIS_URL);

const smartRateLimiter = (req, res, next) => {
    // 1. Anahtar (Key) Oluştur
    const ip = req.ip;
    const userId = req.user?.id || 'anonymous';
    const userTier = req.user?.tier || 'anonymous';
    const path = req.path;

    // Örnek Key: rateLimit:ip:192.168.1.1|user:123|path:/api/search
    const baseKey = `rateLimit:ip:${ip}|user:${userId}|path:${path}`;

    // 2. Uygulanacak Limit Kurallarını Belirle
    const tierRule = rateLimitRules.userTier[userTier];
    const endpointRule = rateLimitRules.endpoints[path];

    const limitsToApply = [];
    if (tierRule) limitsToApply.push({ ...tierRule, keySuffix: 'tier' });
    if (endpointRule) limitsToApply.push({ ...endpointRule, keySuffix: 'endpoint' });

    // 3. Tüm Limitleri Asenkron Kontrol Et
    const checkPromises = limitsToApply.map(async (rule) => {
        const fullKey = `${baseKey}|type:${rule.keySuffix}`;
        const current = await redisClient.incr(fullKey);

        if (current === 1) {
            // İlk istekte, bu anahtar için TTL (süre) belirle
            await redisClient.expire(fullKey, rule.windowMs / 1000);
        }

        if (current > rule.max) {
            throw new Error(`LIMIT_EXCEEDED_${rule.keySuffix.toUpperCase()}`);
        }
        return true;
    });

    Promise.all(checkPromises)
        .then(() => next()) // Tüm limitler aşılmadı, isteği geçir
        .catch((err) => {
            if (err.message.includes('LIMIT_EXCEEDED')) {
                const limitType = err.message.split('_')[2];
                res.status(429).json({
                    error: 'İstek Limiti Aşıldı',
                    message: `${limitType} limitinizi aştınız. Lütfen daha sonra tekrar deneyin.`,
                    retryAfter: limitsToApply.find(r => r.keySuffix === limitType.toLowerCase())?.windowMs / 1000
                });
            } else {
                next(err);
            }
        });
};

// Middleware'i uygula
app.use('/api', smartRateLimiter);

🎯 Sonuç ve Kazanımlar

Bu yapıyı kurduktan sonra inanılmaz rahatladım. Artık:
Kritik /api/checkout endpoint'i, spam ödeme isteklerine karşı çok daha korunaklı.
Premium bir kullanıcı, ücretsiz kullanıcıya göre 5 kat daha fazla API isteği atabiliyor.
/api/auth/login üzerinde bruteforce saldırı riski ciddi oranda azaldı.
Tüm bu kurallar, merkezi Redis sunucusunda tutulduğu için birden fazla sunucu (cluster) kullansak bile tutarlı çalışıyor.

Siz backend API'larınızda rate limiting'i nasıl yönetiyorsunuz? Özellikle mikroservis mimarisinde bu kuralları nasıl merkezileştiriyorsunuz? Benim kullandığım yöntem hakkında düşünceleriniz veya eklemek istedikleriniz var mı? Yorumlarda buluşalım!
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri