Episode ini membahas rate limiting di Fiber v3: middleware limiter dengan Max dan Expiration, KeyGenerator berbasis IP, penanganan LimitReached dengan 429, algoritma sliding window, serta penyimpanan Redis untuk limiter yang dibagikan antar instance.

API publik tanpa perlindungan mudah dibanjiri — entah oleh bot, percobaan brute-force, atau bug pada client. Episode 20 membahas rate limiting di Fiber v3: membatasi jumlah request per client dalam periode waktu, menyesuaikan kunci berdasarkan IP, dan membagikan state limiter lintas instance dengan Redis.
Rate limiting bukan hanya soal keamanan. Ia juga menjaga harga infrastruktur tetap terkendali dan melindungi pengguna lain dari degradasi layanan. Karena itu hampir semua API produksi memakai limiter di lapisan terluar.
limiter.New dari middleware/limiter membatasi jumlah request:
import "github.com/gofiber/fiber/v3/middleware/limiter"
app.Use(limiter.New(limiter.Config{
Max: 20,
Expiration: 30 * time.Second,
}))Max: 20 mengizinkan 20 request per kunci dalam Expiration: 30s. Setelah melewati batas, request ditolak. Tanpa KeyGenerator, kunci default adalah alamat IP client. Ini sudah cukup untuk prototipe, tapi butuh penyesuaian saat berjalan di belakang proxy.
Di belakang reverse proxy, IP client ada di header X-Forwarded-For. Atur KeyGenerator agar membaca dari sumber yang tepat:
app.Use(limiter.New(limiter.Config{
Max: 20,
Expiration: 30 * time.Second,
KeyGenerator: func(c fiber.Ctx) string {
if ip := c.Get("X-Forwarded-For"); ip != "" {
return ip
}
return c.IP()
},
}))KeyGenerator menentukan identitas client. Contoh ini memakai X-Forwarded-For jika tersedia, fallback ke c.IP(). Dengan begitu semua pengguna di belakang satu IP proxy dihitung secara terpisah, dan satu client tidak menguras kuota client lain.
Saat batas terlampaui, LimitReached dipanggil. Sesuaikan agar respons informatif:
app.Use(limiter.New(limiter.Config{
Max: 20,
Expiration: 30 * time.Second,
LimitReached: func(c fiber.Ctx) error {
return c.Status(fiber.StatusTooManyRequests).JSON(fiber.Map{
"error": "terlalu banyak request, coba lagi nanti",
})
},
}))LimitReached menggantikan respons default 429 dengan body JSON yang jelas. Tambahkan header Retry-After jika ingin memberi tahu client kapan boleh mencoba lagi. Respons yang konsisten memudahkan client menangani penolakan dengan benar.
Fiber v3 menerapkan algoritma sliding window — lebih adil daripada fixed window:
app.Use(limiter.New(limiter.Config{
Max: 100,
Expiration: time.Minute,
}))Dengan fixed window, burst request di akhir satu menit dan awal menit berikutnya bisa menggabung menjadi 200 dalam beberapa detik. Sliding window menghitung berdasarkan jendela yang bergeser terus — batas 100 per menit tetap berlaku di titik waktu mana pun. Hasilnya kuota lebih presisi dan sulit dieksploitasi dengan burst di perbatasan waktu.
Defaultnya state limiter tersimpan di memori per instance. Jika aplikasi berjalan di banyak server, masing-masing punya kuota sendiri. Pakai Redis agar limiter konsisten global:
import (
"github.com/gofiber/storage/redis/v3"
"github.com/gofiber/fiber/v3/middleware/limiter"
)
storage := redis.New(redis.Config{
Host: "localhost",
Port: 6379,
Database: 0,
})
app.Use(limiter.New(limiter.Config{
Max: 100,
Expiration: time.Minute,
Storage: storage,
}))limiter.Config{Storage: storage} memakai Redis untuk menyimpan hitungan request. Sekarang pengguna yang membelah kuotanya ke dua server tetap dihitung sekali — total request lintas instance tidak bisa menembus batas. Ini wajib saat aplikasi di-deploy dengan load balancer.
for i in $(seq 1 25); do
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/
done | sort | uniq -cLoop mengirim 25 request. Dengan Max: 20, 20 request pertama mengembalikan 200 dan sisanya 429. Hitungan uniq -c menunjukkan distribusinya. Coba ganti IP di header X-Forwarded-For dan amati bahwa kuota dihitung per client.
Inti yang harus dibawa pulang:
limiter.New(limiter.Config{Max, Expiration}) membatasi request per kunci dalam periode waktu.KeyGenerator menentukan identitas client — baca X-Forwarded-For saat di belakang proxy.LimitReached menyesuaikan respons saat batas tercapai (status 429).limiter.Config{Storage: redis} membagikan state lintas instance untuk aplikasi multi-server.Di episode 21 selanjutnya kita membahas deployment dan Docker — membangun image Fiber dengan output standalone, optimasi multi-stage, variabel lingkungan, dan deploy ke Vercel serta Docker.