Tum Yazilar
yazilim

PostgreSQL + Redis ile Next.js Cache Mimarisi: Üretim Ortamından Pratik Rehber

PostgreSQL + Redis ile Next.js Cache Mimarisi: Üretim Ortamından Pratik Rehber
WG

Web Görsel

2026-04-14T09:11:32.235Z4 dk okuma
Kısa özet: Yüksek trafikli Next.js uygulamalarında cache üç katmandır: edge (Cloudflare / CDN), uygulama seviyesi (Redis), veritabanı (PostgreSQL). Doğru kurguda istekler önce edge''de yakalanır, miss olursa Redis''ten, o da yoksa Postgres''ten gelir. Bu rehber; üç katmanı entegre eden pratik mimari, invalidation stratejileri, tagging ve gerçek kod örnekleriyle production kurulumu anlatır.

Neden Üç Katmanlı Cache?

Her katman farklı bir problemi çözer:

  • Edge cache: Kullanıcıya en yakın, TTFB''yi 20-50 ms''ye indirir
  • Redis: Uygulama seviyesinde paylaşılan bellek, milisaniyede sorgu dönüşü
  • PostgreSQL: Kaynak doğruluk, transactional bütünlük

Katman 1: Edge Cache (Cloudflare / Vercel)

Next.js ISR + Cloudflare Cache Rules kombinasyonu:

// app/blog/[slug]/page.tsx
export const revalidate = 300; // 5 dk ISR

export default async function Sayfa({ params }) {
  const yazi = await getYazi(params.slug);
  return <Article data={yazi} />;
}

Cloudflare tarafında "Cache Everything" + "Origin Cache Control" aktif. Edge 5 dakika boyunca aynı HTML''i verir, stale-while-revalidate ile güncelleme arka planda yapılır.

Katman 2: Redis (Uygulama Cache)

Tipik Kullanımlar

  • Sık sorgulanan agregasyonlar (ör. anasayfa popüler ürünler)
  • Kullanıcı oturum verisi
  • Rate limit sayaçları
  • 3. parti API yanıtları (döviz kuru, hava durumu)
  • Queue (Bull/BullMQ ile)

Kurulum

import { createClient } from ''redis'';

const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();

export async function cache<T>(key: string, fn: () => Promise<T>, ttl = 60) {
  const cached = await redis.get(key);
  if (cached) return JSON.parse(cached) as T;
  const data = await fn();
  await redis.setEx(key, ttl, JSON.stringify(data));
  return data;
}

Kullanım

const urunler = await cache(''populer-urunler'', () =>
  db.urunler.findMany({ where: { populer: true }, take: 12 })
, 300);

Katman 3: PostgreSQL (Kaynak Doğruluk)

Performans Tuning

  • shared_buffers RAM''in %25''i
  • effective_cache_size RAM''in %75''i
  • work_mem bağlantı × 32 MB makul
  • max_connections — PgBouncer ile havuz kullan
  • Sık sorgular için composite index
  • Slow query log aktif, haftalık incele

PgBouncer (Zorunlu)

Serverless / Vercel gibi ortamlarda her fonksiyon Postgres''e ayrı bağlantı açar — bağlantı havuzu hızla tükenir. PgBouncer transaction pooling ile 20 gerçek Postgres bağlantısı üzerinden binlerce uygulama bağlantısı karşılanır.

Invalidation: Cache''i Ne Zaman Temizlersin?

Cache''in en zor problemi. Stratejiler:

1. Zaman bazlı (TTL)

En basit. 5 dakika sonra süresi doluyor. Küçük tutarsızlık kabul edilebilirse iyi.

2. Tag Tabanlı (Next.js 14+)

import { unstable_cache, revalidateTag } from ''next/cache'';

const getUrun = unstable_cache(
  async (id) => db.urunler.findUnique({ where: { id } }),
  [''urun''],
  { tags: [''urun''] }
);

// Admin fiyat güncelleyince
revalidateTag(''urun'');

3. Event Driven

PostgreSQL LISTEN/NOTIFY ile DB değişikliğinde Redis''e sinyal gönder, ilgili key''i sil.

CREATE TRIGGER urun_degisti AFTER INSERT OR UPDATE OR DELETE ON urunler
FOR EACH ROW EXECUTE FUNCTION notify_change(''urun'');

Cache Warming

Soğuk cache kullanıcıyı etkilemesin diye kritik sayfaları önceden ısıt:

  • Cron ile saat başı ana sayfa + popüler kategorileri çağır
  • Build sonrası sitemap''teki ilk 100 URL''yi fetch et
  • Yeni ürün eklendiğinde ilgili kategoriyi tetikle

Gerçek Production Mimarisi

Kullanıcı
   │
   ▼
Cloudflare (edge cache, DDoS, WAF)
   │  miss
   ▼
Vercel / Node.js Next.js
   │
   ├── Redis (oturum, rate limit, agregasyon)
   │
   └── PgBouncer
          │
          ▼
      PostgreSQL (read replica + primary)

Monitoring

  • Cache hit ratio: Redis için > %80 sağlıklı, > %95 mükemmel
  • Postgres slow query (> 200 ms): haftalık rapor
  • Cloudflare cache status: X-Cache-Status header ile
  • p95, p99 yanıt süresi (ortalamalar yanıltır)

Güvenlik

  • Redis''e AUTH şifre ve ACL (Redis 6+)
  • PostgreSQL''e sadece private network''ten erişim
  • Bağlantı dize (connection string) secrets manager''da
  • Cache''e kullanıcıya özel veri koyarken key''e userId ekle (data leak önleme)

Sık Yapılan Hatalar

  1. Cache''i "çözüm" sanıp yavaş sorguları çözmemek
  2. TTL''i sonsuz yapıp stale veri servis etmek
  3. Kullanıcıya özel veriyi genel key altında cachelemek (leak)
  4. PgBouncer olmadan serverless''ten Postgres''e bağlanmak
  5. Cache key''lerde versiyon olmayışı (deploy sonrası karışık veri)
  6. Redis''e çok büyük JSON''lar atmak (1 MB+ öneri edilmez)

Sıkça Sorulan Sorular

Redis yerine memcached olur mu?

Evet ama Redis''in pub/sub, persistence, veri yapıları (sorted set, stream) avantajı var. Modern stack''te Redis standart.

PostgreSQL hem cache hem kaynak olabilir mi?

Olabilir — materialized view + pg_cron. Küçük projelerde Redis''siz mimari mümkün. Büyük trafikte Redis eklemek gerekir.

ISR yeterli mi, Redis şart mı?

ISR HTML cache''ler. Redis veri (JSON/API response) cache''ler. İkisi farklı sorunları çözer.

Cache hit ratio''yu nasıl yükseltirim?

Daha uzun TTL + tag tabanlı invalidation + daha iyi key tasarımı (aynı veriye aynı key). Hot data''yı analiz edip pre-warming ekleyin.

Sonraki Adım

Next.js + PostgreSQL + Redis cache mimarisi kurulumu için teknik görüşme. İlgili: INP Metriği, CDN Karşılaştırma.

Paylaş:

Yorumlar (0)

Yorum Yaz

Bu konuda yardima mi ihtiyaciniz var?

Ekibimiz, projenize en uygun cozumleri sunmak icin hazir.

Iletisime Gecin