Back to homeGet Started
System Architecture Deep-Dive

Redis-Based Real-Time Messaging System

A production-grade design that goes well beyond a basic queue — covering priority delivery, consumer fault tolerance, TTL-based expiry, hybrid push/poll, and Redis-native rate limiting.

Java / Spring BootRedisDockerAWS EC2REST API

Problem Statement

What breaks at scale

Wasteful polling

Continuous polling hammers the server even when there are no messages — wasting CPU and database connections.

No priority handling

Naive queues treat a system alert and an analytics event identically. Critical messages can sit behind thousands of low-priority ones.

Consumer crashes

If a consumer reads a message and then crashes, the message is silently lost with no way to re-deliver or investigate.

Producer floods

Without rate limiting, a single misbehaving producer can exhaust queue capacity, starving every other consumer.

High-Level Architecture

How the system is structured

architecture.txt
  Producer (any HTTP client)
        │
        ▼
  REST API  ─── Spring Boot ─── Rate Limiter (Redis INCR+EXPIRE)
        │
        ▼
  Redis  ─────────────────────────────────────────────────────
  │  Sorted Set  → priority queue  (messages:{channel})      │
  │  Pub/Sub     → real-time push  (channel:*)               │
  │  List        → retry buffer    (retry:{channel})         │
  │  List        → dead-letter     (dlq:{channel})           │
  │  String      → rate counters   (rl:{key}:{window})       │
        │
        ▼
  Consumer Service
  ├─ Supports real-time? → Redis Pub/Sub push
  └─ Polling fallback?   → GET /v1/messages/poll (long-poll)
        │
        ▼
  ACK   → message removed from processing queue
  No ACK within timeout → re-queue (max N retries → DLQ)

Redis Data Structures

Five data structures, five problems solved

Data StructureUse in BlinkQ
Sorted SetsPriority queue — score = priority × 1e9 + unix_ms
Pub/SubReal-time push to consumers that support it
Strings / INCRSliding-window rate limiter per producer key
Key Expiry (TTL)Automatic stale-message cleanup — no cron needed
ListsProcessing queue, retry buffer, and dead-letter queue

Core Innovations

What makes this production-grade

01

Hybrid Push / Poll

Consumers that open a WebSocket or SSE channel receive messages via Redis Pub/Sub with sub-millisecond latency. Consumers that can only poll use long-polling via GET /messages/poll — the server blocks until a message is available or the timeout expires. The switch is transparent to the producer.

02

Priority Queue with Sorted Sets

Each message is inserted into a Redis Sorted Set with score = priority × 10⁹ + unix_ms. ZPOPMAX atomically retrieves the highest-priority, earliest message. Priority 0 = analytics noise; Priority 10 = production incident. No separate queues per priority needed.

03

TTL & Automatic Expiry

Every message carries a TTL field. On publish, Redis EXPIREAT is set on the message key. Stale messages are never delivered — Redis purges them automatically. This eliminates the need for a cleanup cron job and keeps queue memory bounded.

04

ACK-Based Consumer Recovery

After delivering a message, BlinkQ adds it to a processing set with a delivery timestamp. The consumer must POST /messages/ack within a configurable window. If not, the message is moved back to the priority queue. After N failed retries it is appended to the dead-letter queue for manual inspection via GET /dead-letter.

05

Redis-Native Rate Limiting

Each producer API key has a sliding-window rate limit enforced with INCR + EXPIRE. The counter key is namespaced by key + second-aligned window. If the counter exceeds the configured threshold, the API returns HTTP 429. No external rate-limit store needed — Redis handles it atomically.

API Design

Stateless, authenticated, rate-limited

MethodPath
POST/v1/messages
POST/v1/messages/bulk
GET/v1/messages/poll
POST/v1/messages/ack
GET/v1/metrics
GET/v1/dead-letter

Technology Stack

Chosen for performance and simplicity

Java 21 / Spring Boot 3

REST API, business logic, ACK tracking

Redis 7

Message broker, rate limiter, TTL engine

Docker / Docker Compose

Containerised dev & prod environment

AWS EC2

Deployment target for Redis and services

Redis Pub/Sub

Real-time push path for live consumers

Prometheus (optional)

Metrics: queue depth, latency, error rate

Try it yourself

Sign up, generate an API key, and publish your first priority message in under two minutes.