---
title: "PostgreSQL NOTIFY/LISTEN ile Gerçek Zamanlı Bildirim Sistemi"
description: "PostgreSQL pg_notify ve LISTEN mekanizması nasıl çalışır? Trigger ile bildirim gönderme, Node.js'te dinleme ve Supabase Realtime altyapısı rehberi."
date: 2026-04-13
category: veri-muhendisligi
tags: ["postgresql", "notify", "listen", "realtime", "trigger", "nodejs"]
url: https://mikroerp.dev/blog/postgresql-notify-listen-gercek-zamanli/
---

## Polling'e Son: Veritabanı Sana Söylesin

Geleneksel yaklaşım: Her 5 saniyede "yeni veri var mı?" diye sorgulamak (polling). Verimsiz, yavaş, sunucu yükü.

Doğru yaklaşım: Veritabanı kendisi "yeni veri geldi" desin. PostgreSQL'in yerleşik **NOTIFY/LISTEN** mekanizması bunu sağlar.

## NOTIFY/LISTEN Nasıl Çalışır?

```
Uygulama A                   PostgreSQL                   Uygulama B
    │                            │                            │
    │  INSERT INTO orders(...)   │                            │
    │───────────────────────────>│                            │
    │                            │  NOTIFY 'new_order'        │
    │                            │───────────────────────────>│
    │                            │        payload: {...}      │
    │                            │                            │
```

1. **NOTIFY**: Bir kanala mesaj gönderir
2. **LISTEN**: Bir kanalı dinlemeye başlar
3. **Payload**: Mesajla birlikte veri taşır (max 8000 byte)

## NOTIFY ile Mesaj Gönderme

```sql
-- Basit bildirim
NOTIFY new_order, 'Sipariş #1234 oluşturuldu';

-- JSON payload ile
SELECT pg_notify(
  'stock_alert',
  json_build_object(
    'product_id', 42,
    'stock', 3,
    'message', 'Kritik stok seviyesi!'
  )::text
);
```

## Trigger ile Otomatik Bildirim

```sql
CREATE OR REPLACE FUNCTION notify_new_order()
RETURNS TRIGGER AS $$
BEGIN
  PERFORM pg_notify(
    'new_order',
    json_build_object(
      'id', NEW.id,
      'customer', NEW.customer_name,
      'total', NEW.total_amount,
      'created_at', NEW.created_at
    )::text
  );
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER order_created_notify
AFTER INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION notify_new_order();
```

Bu trigger sayesinde `orders` tablosuna her INSERT olduğunda bağlı tüm dinleyiciler otomatik bildirim alır.

## Node.js ile LISTEN

```typescript
import { Client } from 'pg';

const client = new Client({
  connectionString: process.env.DATABASE_URL,
});

async function startListening() {
  await client.connect();
  
  // Kanalı dinlemeye başla
  await client.query('LISTEN new_order');
  await client.query('LISTEN stock_alert');
  
  // Bildirim geldiğinde
  client.on('notification', (msg) => {
    console.log('Kanal:', msg.channel);
    
    const payload = JSON.parse(msg.payload || '{}');
    console.log('Veri:', payload);
    
    // İstediğiniz aksiyonu alın
    if (msg.channel === 'stock_alert') {
      sendSlackNotification(payload);
    }
    
    if (msg.channel === 'new_order') {
      broadcastToWebSocket(payload);
    }
  });
  
  console.log('Dinleniyor: new_order, stock_alert');
}

startListening().catch(console.error);
```

## Stok Kritik Seviye Uyarısı

```sql
-- Stok seviyesi 5'in altına düştüğünde bildirim
CREATE OR REPLACE FUNCTION check_stock_level()
RETURNS TRIGGER AS $$
BEGIN
  IF NEW.quantity <= 5 AND (OLD.quantity IS NULL OR OLD.quantity > 5) THEN
    PERFORM pg_notify(
      'stock_alert',
      json_build_object(
        'product_id', NEW.product_id,
        'product_name', (SELECT name FROM products WHERE id = NEW.product_id),
        'quantity', NEW.quantity,
        'warehouse', NEW.warehouse_id
      )::text
    );
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER stock_level_check
AFTER UPDATE ON inventory
FOR EACH ROW
EXECUTE FUNCTION check_stock_level();
```

## Supabase Realtime vs NOTIFY/LISTEN

Supabase Realtime aslında **NOTIFY/LISTEN üzerine** kurulmuştur:

| Özellik | Ham NOTIFY/LISTEN | Supabase Realtime |
|---------|:---:|:---:|
| Altyapı | Kendi sunucunuz | Supabase managed |
| Bağlantı | PostgreSQL connection | WebSocket |
| RLS desteği | Manuel | Otomatik |
| Client SDK | Yok | `supabase-js` |
| Ölçeklenme | Sınırlı | Auto-scale |

## Polling vs NOTIFY Performans Karşılaştırması

| Metrik | Polling (5sn) | NOTIFY/LISTEN |
|--------|:---:|:---:|
| Gecikme | 0-5 saniye | ~10ms |
| Sorgu sayısı/dakika | 12 | 0 (sadece bildirim) |
| Sunucu yükü | Sabit (gereksiz) | Sadece değişiklikte |
| Bağlantı | Her sorguda | Sürekli (1 connection) |

## Dikkat Edilecekler

1. **Payload limiti**: 8000 byte. Büyük veri göndermeyin — sadece ID/key gönderin.
2. **Bağlantı kopması**: LISTEN bağlantısı koparsa bildirimler kaybolur. Reconnect mantığı ekleyin.
3. **Transaction**: NOTIFY, transaction commit edilene kadar gönderilmez.
4. **Connection pool**: LISTEN için **ayrı bir bağlantı** kullanın, pool'dan değil.

## İlgili Yazılar

- [PostgreSQL Trigger Fonksiyonları](/blog/postgresql-trigger-fonksiyonlari-rehberi/) — Trigger yazma rehberi
- [Supabase Edge Functions](/blog/supabase-edge-functions-bildirim-sistemi/) — Bildirim altyapısı
- [pg_cron Zamanlanmış Görevler](/blog/postgresql-pg-cron-zamanlanmis-gorevler/) — Polling alternatifi

---

*Bu rehber [PostgreSQL NOTIFY Docs](https://www.postgresql.org/docs/current/sql-notify.html) ve [pg_listen](https://www.postgresql.org/docs/current/sql-listen.html) dokümantasyonuna dayanarak hazırlanmıştır.*