Overview
Vote4GOAT is a real-time election monitoring system built for the 2024 academic election cycle. The system needed to handle concurrent vote submissions, provide live tally updates to authenticated observers, and maintain an immutable audit log.
Architecture
Seven services in Docker Compose:
| Service | Role | |---|---| | Django | Application server, REST API, admin | | Postgres | Source of truth for votes and users | | Kafka | Event stream for vote events and tally updates | | Redis | Cache for live tally aggregates | | Keycloak | SSO and RBAC (voters, observers, admins) | | Nginx | Reverse proxy and static file serving | | Celery | Background workers for tally computation |
Event flow
- Voter authenticates via Keycloak (OIDC)
- Vote submission → Django validates eligibility → writes to Postgres → emits Kafka event
- Celery consumer reads Kafka event → updates Redis tally aggregate
- Observer dashboard polls Redis for live counts (1-second intervals)
- All events written to immutable audit log in Postgres (append-only table, no UPDATE/DELETE)
Key decisions
Kafka for vote events — even at this scale, the event log was valuable for post-election audit and replay. The operational vocabulary (consumer groups, offsets) matched what the audit requirements needed.
Keycloak for SSO — role separation (voter / observer / admin) was a hard requirement. Hand-rolling it would have been risky; Keycloak got us RBAC and a proper token flow in an afternoon.
Redis for live tallies — Postgres can handle the write load, but the observer dashboard at peak had ~50 concurrent pollers. Caching the aggregates in Redis reduced DB load by ~80%.