Back to homeGet started
Current backend architecture

Retained Priority Messaging System

A Spring Boot API separates session-authenticated browser management from project-key-authenticated external messaging, backed by durable relational resources and expiring Redis queue data.

Spring BootMySQLRedisSession + CSRFBearer project keys

Security boundaries

Two authentication models, separate routes

Browser dashboard

Opaque HttpOnly sessions authenticate account, project, channel, and dashboard-message routes. Every mutation also sends an in-memory, session-bound CSRF token.

External messaging

Only /messages and /messages/poll accept a project Bearer key. Raw keys are shown once; the backend persists their SHA-256 hashes.

Request flow

How data moves through BlinkQ

architecture.txt
Browser dashboard                 External service
Session cookie + CSRF             Bearer project key
        │                                 │
        └──────────────┬──────────────────┘
                       ▼
                 Spring Boot API
                  │            │
                  ▼            ▼
        MySQL resources     Redis queue data
        users/projects      payload string + TTL
        channels/key hash   sorted-set member IDs
                                 │
                                 ▼
                  inspect or poll (non-destructive)

Storage

Durable resources, expiring messages

StoreUse in BlinkQ
MySQLDurable users, projects, channel definitions, and hashed project API keys
Redis sessionsOpaque browser sessions used by dashboard routes
Redis stringsMessage payload records with millisecond TTL expiry
Redis sorted setsPer-channel retained member IDs ordered by priority and timestamp
Redis cacheShort-lived API-key-hash to project lookups
Redis Pub/SubInternal new-message wake-up signal; not a browser or consumer subscription API

Queue semantics

What retained messaging means

Priority 1–5

Priority 5 sorts first; older timestamps sort first among records with the same priority.

Positive TTL

Payload keys expire in Redis. The browser receives an approximate remaining TTL in milliseconds.

Non-destructive reads

Dashboard inspection and external polling do not consume, acknowledge, or remove live records.

Approximate membership

The sorted-set count can temporarily include IDs whose payload keys have expired.

Ownership masking

Missing and foreign project/channel IDs both appear as not found to avoid leaking ownership.

One-time credentials

Project creation and rotation are the only responses that reveal a raw API key.

API surface

Implemented endpoints

MethodPathBehavior
GET/auth/csrfBootstrap a session-bound CSRF token
POST/auth/signup · /auth/signinCreate or authenticate a user session
GET/projects · /channelsRead owned dashboard resources
POST/projects · /channelsCreate owned resources with session + CSRF
GET/channels/{id}/messagesInspect up to 100 retained records non-destructively
POST/channels/{id}/messagesPublish from the authenticated dashboard
GET/channels/{id}/statsRead approximate retained membership
POST/messagesExternal Bearer-key publish
GET/messages/pollExternal Bearer-key non-destructive poll

Deliberate current boundaries

The current API does not provide acknowledgement/consume operations, retries, dead-letter queues, bulk publishing, external WebSocket/SSE delivery, per-key rate limiting, or durable message history. Polling can return the same retained record more than once.

Try the implemented flow

Create an account and project, save its one-time key, add a channel, and publish from the dashboard or external API.

Create account