Applications send us events. We turn them into real-time analytics.
PulseFlow ingests activity events via REST, processes them asynchronously through RabbitMQ, persists data in PostgreSQL, caches hot statistics in Redis, and streams live updates to a React dashboard over WebSocket β all orchestrated with Docker Compose in a single command.
Quick Start Β· Architecture Β· API Reference Β· Contributing
- Why PulseFlow?
- Key Features
- Architecture
- Tech Stack
- Quick Start
- Local Development
- API Reference
- Project Structure
- Environment Variables
- Testing
- Deployment
- Roadmap
- Contributing
- License
Most backend portfolio projects are simple CRUD applications with a database. PulseFlow goes further β it demonstrates production-grade backend engineering patterns that power systems at scale:
| Concept | How PulseFlow Implements It |
|---|---|
| Event-Driven Architecture | Decoupled producers and consumers via RabbitMQ message broker |
| Asynchronous Processing | POST /events returns 202 Accepted instantly β zero synchronous DB writes on the hot path |
| Caching Strategy | Redis as a fast, disposable accelerator; PostgreSQL as the source of truth |
| Real-Time Delivery | WebSocket (STOMP) pushes live updates; automatic REST polling fallback on disconnect |
| Failure Resilience | Dead-letter queues, exponential backoff retries, failed_events table β no event is silently lost |
| Security | JWT authentication for admins, API key-based auth for event ingestion, BCrypt password hashing |
| Containerized Infrastructure | Full-stack Docker Compose with health-checked dependencies |
- β‘ High-throughput event ingestion β sub-100ms response via async publish to RabbitMQ
- π RabbitMQ consumer pipeline β idempotent processing with configurable retry policy and dead-letter queue
- ποΈ PostgreSQL persistence β durable event storage with JSONB metadata, pagination, and filtering
- π Redis caching layer β namespaced counters, sorted sets, and HyperLogLog for real-time analytics
- π Dual authentication β JWT (HS256) for admin dashboard, API key (
X-API-Key) for machine clients - π Analytics REST API β summary, daily trends, top events, top users, and real-time snapshots
- π WebSocket broadcasting β STOMP-over-SockJS pushes processed events and stat updates live
- π OpenAPI documentation β auto-generated Swagger UI at
/swagger-ui.html - π‘οΈ Rate limiting β configurable per-key request throttling on the ingestion endpoint
- π₯ Health & monitoring β queue depth, consumer status, Redis health, and audit logging
- π Live dashboard β real-time counters with animated updates on every processed event
- π Interactive charts β daily trend line chart and top events bar chart (Recharts)
- π Event log β paginated, filterable event browser with detail view
- π Graceful degradation β auto-fallback from WebSocket to REST polling with reconnect indicator
- π¨ Instrument-panel aesthetic β dark theme, JetBrains Mono typography, glassmorphism UI
flowchart TB
subgraph Clients
ClientApp["π₯οΈ Client Application"]
end
subgraph Ingestion["Ingestion Layer"]
API["Spring Boot REST API<br/><i>Validates + publishes only</i>"]
end
subgraph Messaging["Message Broker"]
RMQ["RabbitMQ<br/><i>events.queue + DLQ</i>"]
end
subgraph Processing["Processing Layer"]
Consumer["Analytics Consumer<br/><i>Idempotent processing</i>"]
end
subgraph Storage["Storage Layer"]
PG[("PostgreSQL<br/><i>Source of truth</i>")]
Redis[("Redis<br/><i>Hot cache</i>")]
end
subgraph Delivery["Delivery Layer"]
WS["WebSocket Broadcaster<br/><i>STOMP over SockJS</i>"]
AnalyticsAPI["Analytics REST API"]
end
subgraph Frontend["Frontend"]
Dashboard["β‘ React Dashboard"]
end
ClientApp -->|"POST /events<br/>X-API-Key"| API
API -->|"publish EventMessage"| RMQ
RMQ --> Consumer
Consumer -->|"persist event"| PG
Consumer -->|"update counters"| Redis
Consumer -->|"broadcast"| WS
AnalyticsAPI -->|"read"| PG
AnalyticsAPI -->|"read cached stats"| Redis
Dashboard -->|"REST + JWT"| AnalyticsAPI
Dashboard -->|"subscribe live"| WS
style Clients fill:#1a1a2e,stroke:#5EEAA0,color:#E8F5E9
style Ingestion fill:#16213e,stroke:#5EEAA0,color:#E8F5E9
style Messaging fill:#0f3460,stroke:#FF6600,color:#E8F5E9
style Processing fill:#16213e,stroke:#5EEAA0,color:#E8F5E9
style Storage fill:#1a1a2e,stroke:#4169E1,color:#E8F5E9
style Delivery fill:#16213e,stroke:#61DAFB,color:#E8F5E9
style Frontend fill:#1a1a2e,stroke:#61DAFB,color:#E8F5E9
| Decision | Rationale |
|---|---|
| Ingestion is publish-only | POST /events never touches Postgres or Redis synchronously β guarantees sub-100ms latency regardless of downstream load |
| Single writer principle | The RabbitMQ consumer is the sole writer for event data β centralizes retry/failure logic and eliminates race conditions |
| Redis is disposable | Every Redis key is reconstructible from Postgres β cache failures never cause data loss |
| WebSocket + polling fallback | Dashboard never goes blank β automatically switches to 5s REST polling if WebSocket disconnects |
| Dead-letter queue | Failed messages are retried with exponential backoff, then routed to DLQ + failed_events table β zero silent data loss |
| Layer | Technology | Purpose |
|---|---|---|
| Language | Java 21 LTS | Modern LTS with virtual threads support |
| Framework | Spring Boot 3.5 | Web, Security, Data JPA, AMQP, WebSocket, Validation |
| Database | PostgreSQL 16 | Durable event storage with JSONB, indexing, and full-text search |
| Cache | Redis 7 | Counters, sorted sets, HyperLogLog for real-time analytics |
| Message Broker | RabbitMQ 3.x | Topic exchange, dead-letter queue, management plugin |
| Frontend | React 19 + Vite 8 | SPA dashboard with STOMP.js WebSocket client |
| Charting | Recharts 3.9 | Interactive line and bar charts |
| Auth | Spring Security + JWT | HS256 token-based authentication |
| API Docs | springdoc-openapi 2.8 | Auto-generated Swagger UI |
| Testing | JUnit 5 + Testcontainers | Integration tests with real Postgres, Redis, and RabbitMQ |
| Infrastructure | Docker Compose | Full-stack orchestration with health checks |
| Reverse Proxy | Nginx | Frontend static serving + API/WebSocket proxying |
- Docker & Docker Compose installed
- Ports
3000,5432,5672,6379,8082,15672available
# Clone the repository
git clone https://github.com/Abdul-Rafy2005/pulseflow.git
cd pulseflow
# Copy environment config
cp .env.example .env
# Start the full stack (Postgres, Redis, RabbitMQ, Backend, Frontend)
docker compose up -d --build| Service | URL | Credentials |
|---|---|---|
| π Dashboard | http://localhost:3000 | Register via UI |
| π Backend API | http://localhost:8082 | JWT / API Key |
| π Swagger UI | http://localhost:8082/swagger-ui.html | β |
| π RabbitMQ UI | http://localhost:15672 | guest / guest |
# 1. Register an admin account
curl -X POST http://localhost:8082/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"admin","email":"admin@example.com","password":"password123"}'
# 2. Fire 50 sample events (requires Python + requests)
python scratch/send_events.py 50 0.5Tip: Set
BACKEND_URLandAPI_KEYinscratch/send_events.pyif not using default values.
docker compose up -d postgres redis rabbitmqcd backend
./mvnw spring-boot:runThe backend starts on port 8080 (or as configured in SERVER_PORT).
cd frontend
npm install
npm run devDashboard dev server runs at http://localhost:5173 with API proxy to backend.
Full interactive documentation is available at /swagger-ui.html when the backend is running. See also docs/api.md for the full endpoint reference.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/auth/register |
None | Create an admin account |
POST |
/auth/login |
None | Authenticate and receive JWT |
GET |
/auth/profile |
JWT | Get current user profile |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/events |
API Key | Ingest event β returns 202 Accepted immediately |
GET |
/events |
JWT | Paginated & filterable event list |
GET |
/events/{id} |
JWT | Single event detail |
Example β Ingest an event:
curl -X POST http://localhost:8082/events \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"eventType": "PAGE_VIEW",
"userId": 42,
"source": "my-app",
"metadata": {"page": "/dashboard", "device": "Desktop", "country": "PK"}
}'Supported Event Types:
LOGIN Β· LOGOUT Β· REGISTER Β· SEARCH Β· PAGE_VIEW Β· BUTTON_CLICK Β· PURCHASE Β· VIDEO_PLAY Β· LIKE Β· COMMENT Β· SHARE Β· DOWNLOAD
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/analytics/summary |
JWT | Today's aggregated totals (Redis-first) |
GET |
/analytics/daily |
JWT | Time-series data for the last N days |
GET |
/analytics/top-events |
JWT | Ranked event types by frequency |
GET |
/analytics/top-users |
JWT | Most active users ranked |
GET |
/analytics/realtime |
JWT | Live snapshot for dashboard initialization |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/health |
None | Liveness / readiness probe |
GET |
/queue/status |
JWT | Queue depth, consumer count, DLQ size |
GET |
/redis/status |
JWT | Connection health, key count, memory usage |
| Endpoint | Protocol | Topics |
|---|---|---|
/ws |
STOMP over SockJS | /topic/events (live event stream) Β· /topic/stats (live counters) |
pulseflow/
βββ backend/ # Spring Boot application
β βββ src/main/java/com/pulseflow/backend/
β β βββ auth/ # JWT auth, registration, login, role guards
β β βββ events/ # Event ingestion, validation, RabbitMQ publishing
β β βββ queue/ # RabbitMQ exchange, queue, bindings, DLQ config
β β βββ analytics/ # Consumer logic, aggregation, Redis R/W, REST APIs
β β βββ dashboard/ # WebSocket config + broadcast service
β β βββ monitoring/ # Health checks, queue/Redis status, audit logs
β β βββ config/ # Security, CORS, Swagger, exception handling
β β βββ common/ # Shared DTOs, utilities, constants
β βββ src/test/ # Unit + integration tests (Testcontainers)
β βββ Dockerfile # Multi-stage build
β βββ pom.xml # Maven dependencies
β
βββ frontend/ # React SPA (Vite)
β βββ src/
β β βββ components/
β β β βββ LoginPage.jsx # Authentication UI
β β β βββ HeroStrip.jsx # Real-time stat counters
β β β βββ DailyTrendChart.jsx # Line chart β events over time
β β β βββ TopEventsChart.jsx # Bar chart β event type distribution
β β β βββ RecentEvents.jsx # Live event stream feed
β β β βββ EventsLog.jsx # Paginated event browser
β β β βββ ConnectionStatus.jsx # WebSocket status indicator
β β βββ services/
β β β βββ api.js # REST client (auth, analytics, events)
β β β βββ websocket.js # STOMP WebSocket client + reconnection
β β βββ App.jsx # Main application with routing
β β βββ index.css # Design system (dark theme, animations)
β βββ nginx.conf # Reverse proxy for API + WebSocket
β βββ Dockerfile # Production build + Nginx
β
βββ docs/
β βββ PRD.md # Product Requirements Document
β βββ api.md # Full API specification
β βββ AGENT.md # Development guidelines
β
βββ scratch/
β βββ send_events.py # Load testing / demo event generator
β
βββ docker-compose.yml # Full-stack orchestration
βββ .env.example # Environment variable template
βββ .gitignore
Copy .env.example to .env before running. Never commit .env to version control.
| Variable | Required | Default | Description |
|---|---|---|---|
JWT_SECRET |
β | β | HS256 signing key (β₯32 bytes) |
EVENTS_API_KEY |
β | β | Required X-API-Key header for event ingestion |
SPRING_DATASOURCE_URL |
β | jdbc:postgresql://localhost:5432/pulseflow |
PostgreSQL connection string |
SPRING_DATASOURCE_USERNAME |
β | pulseflow |
Database user |
SPRING_DATASOURCE_PASSWORD |
β | pulseflow |
Database password |
SPRING_RABBITMQ_HOST |
β | localhost |
RabbitMQ hostname |
SPRING_DATA_REDIS_HOST |
β | localhost |
Redis hostname |
EVENTS_RATE_LIMIT_MAX |
β | 100 |
Max ingestion requests per window |
EVENTS_RATE_LIMIT_WINDOW_SECONDS |
β | 60 |
Rate limit window duration |
JWT_EXPIRATION |
β | PT24H |
Token expiration (ISO 8601 duration) |
SERVER_PORT |
β | 8080 |
Backend server port |
cd backend
./mvnw test- Unit tests β service layer logic, validation, DTOs
- Integration tests β full ingest β queue β consume β persist pipeline using Testcontainers (Docker required)
docker compose up -d --buildBrings up the entire stack with health-checked dependencies. Change JWT_SECRET and EVENTS_API_KEY before any non-local deployment.
Build with backend/Dockerfile and point environment variables at your managed Postgres, Redis, and RabbitMQ instances.
Build with frontend/Dockerfile β serves static assets via Nginx and proxies /api and /ws to the backend service.
- Set strong, unique values for
JWT_SECRETandEVENTS_API_KEY - Restrict RabbitMQ management UI (port
15672) access - Enable TLS/HTTPS termination
- Configure log aggregation for structured JSON logs
- Set up database backups for PostgreSQL
- Multi-tenant support β isolated analytics per client organization
- Anomaly detection consumer β flag unusual event patterns
- Alerting system β Slack/email notifications on queue backlog or anomalies
- Event replay endpoint β manually replay events from the dead-letter queue
- Grafana integration β metrics dashboards and alerting
- Horizontal scaling β Kubernetes manifests for production deployments
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is open source and available under the MIT License.
Built by Abdul Rafy
If this project helped you or you found it interesting, please consider giving it a β