A distributed, event driven real time voting platform designed for high throughput ingestion, sub second latency, and horizontal scalability.
- βοΈ Backend Documentation β Detailed Flask API contracts, Kafka consumer logic, and DB migrations.
- π¨ Frontend Documentation β React setup, state management, UI components, and WebSocket hooks.
- π οΈ Infra structure Docs β Multi container local infrastructure orchestrating.
- High Throughput: Non blocking vote ingestion capable of buffering spikes using Kafka.
- Real-Time Delivery: Instant UI updates via WebSockets powered by Redis Pub/Sub.
- Fault Tolerance: At least once message processing with decoupled producer/consumer components.
- Scalability: Fully containerized components ready for horizontal scaling.
| Layer | Technology | Role |
|---|---|---|
| Frontend | React, Tailwind CSS | Client UI & real time result displays |
| Ingestion API | Flask, Gunicorn | High speed, stateless vote ingestion |
| Message Broker | Apache Kafka, Zookeeper | Event streaming, decoupling, & rate buffering |
| Worker Queue | Python Consumers | Parallel event aggregation & state sync |
| Cache & Pub/Sub | Redis | In memory count storage & WebSocket fan-out |
| Realtime Engine | WebSocket Server | Sub second push notifications to UI |
| Orchestration | Docker, Docker Compose | Infrastructure deployment |
graph TD
subgraph ClientLayer ["Client Layer"]
REACT["Frontend<br/>(React)"]
end
subgraph Ingestion ["Ingestion & Queue"]
FLASK["Flask API<br/>(Producer)"]
KAFKA["Kafka<br/>(Broker)"]
end
subgraph Processing ["Processing & Storage"]
CONSUMERS["Consumers"]
REDIS[("Redis<br/>(Cache + Pub/Sub)")]
end
subgraph Realtime ["Real-Time Delivery"]
WS["WebSocket<br/>Server"]
end
%% Flow Connections
REACT -->|"1. HTTP POST /vote"| FLASK
FLASK -->|"2. Produce Event"| KAFKA
KAFKA -->|"3. Consume Event"| CONSUMERS
CONSUMERS -->|"4. Atomic INCRBY"| REDIS
REDIS -->|"5. Pub/Sub Event"| WS
WS -->|"6. Push Update"| REACT
%% Styling
classDef client fill:#1e293b,stroke:#38bdf8,stroke-width:2px,color:#fff
classDef service fill:#1e293b,stroke:#818cf8,stroke-width:2px,color:#fff
classDef streaming fill:#1e293b,stroke:#fbbf24,stroke-width:2px,color:#fff
classDef storage fill:#1e293b,stroke:#f43f5e,stroke-width:2px,color:#fff
class REACT client
class FLASK,CONSUMERS,WS service
class KAFKA streaming
class REDIS storage
sequenceDiagram
participant F as Frontend (React)
participant A as Flask API
participant K as Kafka Broker
participant C as Consumer Worker
participant R as Redis
participant W as WebSocket Server
F->>A: POST /vote (poll_id, option)
activate A
A->>K: Produce "vote_event" (Partition key: poll_id)
K-->>A: Ack
A-->>F: 202 Accepted (Non-blocking)
deactivate A
K->>C: Consume Event Batch
activate C
C->>R: INCRBY poll:{id}:{option}
C->>R: PUBLISH poll_updates
deactivate C
R->>W: Receive Pub/Sub
activate W
W->>F: Broadcast JSON payload via WebSockets
deactivate W
Note right of F: UI updates instantly without refresh
-
Design Strategy: Immediate return (
$202\text{ Accepted}$ ) upon successfully publishing to Kafka. -
Payload:
{
"user_id": "u123",
"poll_id": "p456",
"option": "A",
"timestamp": "2026-03-19T10:00:00Z"
}- Topic :
votes - Partition Key:
poll_id(Ensures strict ordering of votes per individual poll).
-
Hash Storage: poll:{poll_id}
$\rightarrow$ {"A": 120, "B": 95} -
Pub/Sub Channel:
poll_updates
Prerequisites:
- Docker Desktop
- Python 3.9+
- Node.js 18+
1. Boot Infrastructure (Kafka & Redis)
docker-compose up -d2. Run Local Services Follow the setup guides in each module directory:
-
Backend Service Setup
-
Frontend Application Setup
-
TERMINAL 1: Infrastructure
cd realtime-voting-system
docker-compose up -d- TERMINAL 2: Flask API
cd backend
source venv/bin/activate
python run.py- TERMINAL 3: Kafka Consumer
cd backend
source venv/bin/activate
python -m backend.app.consumers.vote_consumer- TERMINAL 4: WebSocket Server
cd backend
source venv/bin/activate
python websocket_server.py- TERMINAL 5: Frontend
cd frontend
npm install # first time only
npm run devcd backend
pytest tests/test_smoke.py -v
pytest tests/test_vote.py -v- Open http://localhost:3000
- Click "Create Your First Poll"
- Enter question, options, pick duration
- Submit β redirects to new poll
- Vote on an option β confetti + live count updates
- Open second browser/incognito β vote as different user
- Watch both browsers update in real-time
- Wait for timer to expire β winner banner appears
| Issue | Fix |
|---|---|
Port 5000 already in use |
lsof -ti:5000 | xargs kill -9 |
ModuleNotFoundError |
pip install -r requirements.txt |
Kafka not connecting |
Wait 10s after docker-compose up, then retry |
CORS error in browser |
Check VITE_API_URL matches http://localhost:5000/api |
Socket not updating |
Check WebSocket server is running on port 8000 |
npm install fails |
Delete node_modules and package-lock.json, retry |
| Service | Address | Access |
|---|---|---|
| React Frontend | http://localhost:3000 | Web UI |
| Flask API | http://localhost:5000 | REST API |
| WebSocket Server | ws://localhost:8000 | Socket Connection |
| Kafka Broker | localhost:9092 | Internal Queue |
| Redis Server | localhost:6379 | Cache / PubSub |
| Challenge | Architecture Solution |
|---|---|
| Traffic Spikes | Kafka buffers incoming votes; Flask processes non blocking requests. |
| Database Overload | Direct updates bypass persistent DBs, writing directly to Redis in memory structures. |
| Consumer Lag | Increase partition count on the votes topic and scale the Consumer Group workers horizontally. |
| Duplicate Votes | Process idempotency keys inside consumer workers before persisting updates. |
-
Fork the project repository.
-
Create your feature branch: git checkout -b feature/AmazingFeature
-
Commit your updates: git commit -m 'Add some AmazingFeature'
-
Push to the branch: git push origin feature/AmazingFeature
-
Open a Pull Request targeting the main branch.

