Files
coo1estguy 7dedd44c92 feat: prune acked stream entries and make idempotency TTL configurable
- Delete stream messages with XDEL immediately after XACK to free Redis memory and prevent re-processing on recreated consumer groups

- Add IDEMPOTENCY_TTL_SECONDS config (default 1h) for internal stage deduplication

- Preserve 24h idempotency window specifically for client-provided X-Idempotency-Key

- Update queue and pipeline tests to assert deletion on ack and verify TTL behavior
2026-10-05 22:33:17 +05:30

50 lines
3.1 KiB
Bash

# ── Core ──────────────────────────────────────────────────────────────────────
NODE_ENV=development
LOG_LEVEL=debug
PORT=3000
# Bind address. 127.0.0.1 keeps the server off the network; use 0.0.0.0 in a container.
HOST=127.0.0.1
# ── Dependencies ──────────────────────────────────────────────────────────────
# Omit both in development and notifkit starts throwaway containers for you.
REDIS_URL=redis://localhost:6379
DATABASE_URL=postgres://platform:platform@localhost:5432/notifkit
# ── Auth ──────────────────────────────────────────────────────────────────────
# Bootstrap key. Full access to every project — mint per-project keys for apps.
ADMIN_API_KEY=my_super_secret_admin_key
# Allowed origins for CORS on session-authenticated admin endpoints (comma-separated).
# CORS_ORIGIN=https://dashboard.example.com
# ── Unsubscribe ───────────────────────────────────────────────────────────────
# Signs unsubscribe tokens. Minimum 16 characters. Required in production. Treat it as permanent:
# rotating it breaks every unsubscribe link already sitting in an inbox, and a
# dead unsubscribe link sends people to the spam button instead.
# Where an inbox can reach this API. Not HOST/PORT, which are the bind address
# behind your proxy.
PUBLIC_URL=https://notify.example.com
UNSUBSCRIBE_SECRET=change_me_to_a_long_random_string
# ── Limits ────────────────────────────────────────────────────────────────────
# Per-user sliding-window cap. `critical` priority bypasses it.
RATE_LIMIT_PER_HOUR=100
# Largest segment or topic fan-out. A send exceeding this is rejected whole,
# not truncated, so raise it before your list grows past it.
SEGMENT_MAX_USERS=10000
# In-flight messages a worker will process concurrently.
WORKER_CONCURRENCY=10
# Redis stream trim length. The cap on unconsumed backlog.
QUEUE_MAX_LEN=100000
# How long each stage remembers a message it handled (seconds). Must outlast
# redelivery plus your worst backlog; X-Idempotency-Key is always kept 24 hours.
IDEMPOTENCY_TTL_SECONDS=3600
# Postgres pool size, per process. Multiply by your replica count.
DB_MAX_CONNECTIONS=2
# ── Log buffering ─────────────────────────────────────────────────────────────
# Delivery logs are batched into Postgres. Lower the interval for fresher logs,
# raise the buffer for fewer writes under load.
LOG_FLUSH_INTERVAL_MS=500
LOG_BUFFER_MAX_SIZE=5000