SYSTEM_DESIGN
System Design: Electronic Voting System
Architect a secure, auditable electronic voting system supporting millions of concurrent voters with verifiable results and tamper-proof audit trails. Covers security, anonymity, availability, and end-to-end verifiability.
Requirements
Functional Requirements:
- Voter registration and eligibility verification before ballot issuance
- Cast votes anonymously with a cryptographic receipt for personal verification
- Support multiple election types: single choice, ranked-choice, referenda
- Real-time vote tallying with results published after polls close
- Audit capability: any observer can verify the tally without seeing individual votes
- Prevent double-voting: each eligible voter may cast exactly one ballot
Non-Functional Requirements:
- 99.999% availability on election day — downtime is a democratic crisis
- Vote anonymity guaranteed even if the database is compromised
- Full end-to-end verifiability: voters can confirm their vote was counted as cast
- Sub-2-second ballot submission response for 99th percentile
- All audit records permanently immutable and publicly verifiable
Scale Estimation
For a national election with 100M eligible voters: assume 60% turnout = 60M votes. Polls are open for 12 hours = 60M / 43,200 seconds = ~1,389 votes/second average. With a lunch-hour surge at 3x average = ~4,200 votes/second peak. Each ballot submission is ~2KB including cryptographic proofs. Audit log entries: ~100M records at 1KB each = 100GB.
High-Level Architecture
The system is divided into four independently secured tiers: Voter Authentication, Ballot Issuance, Vote Casting, and Tallying. These tiers are air-gapped from each other as much as possible, communicating only through well-defined cryptographic interfaces. The Voter Authentication tier handles identity; it knows who voted but never sees ballot choices. The Vote Casting tier receives encrypted ballots; it knows choices were submitted but not by whom.
The core cryptographic mechanism is a blind signature scheme or a mix-net. In the blind signature approach: the voter's client blinds the ballot, sends the blinded form to the Authentication tier for signing (proving eligibility), then submits the unblinded signed ballot anonymously to the Casting tier. The Casting tier validates the signature came from a legitimate authority without learning voter identity.
End-to-end verifiability is achieved through a cryptographic commitment scheme. Before polls open, the system publishes a commitment to the encryption keys. Each submitted ballot receives a unique tracking code; voters can use this code post-election to verify their encrypted vote appears in the public bulletin board and was correctly decrypted in the tally.
Core Components
Voter Authentication & Eligibility Service
Validates voter identity against the electoral roll. Issues a one-time cryptographic token upon successful authentication. Stores a "has voted" flag per voter (boolean, not linked to ballot content) to prevent double-voting. This flag is set atomically when the token is redeemed at the Casting tier. Uses HSM-backed signing keys to issue eligibility tokens. All authentication events are logged to an immutable audit store.
Ballot Issuance Service
Issues the digital ballot form corresponding to the voter's assigned races (varies by jurisdiction/precinct). Ballot templates are version-controlled and published publicly before elections open. The service does not record which ballot was issued to which voter — only that a ballot was issued to an authenticated session. Ballot integrity is protected by a server-signed hash of the ballot template version.
Vote Casting & Bulletin Board
Receives submitted ballots (each encrypted with the Tally Authority's public key), validates the eligibility signature, checks the token has not been redeemed, marks it redeemed atomically, and appends the encrypted ballot to a public bulletin board (an append-only, publicly auditable log). The bulletin board is replicated across multiple independent organizations (government, civil society observers) to prevent tampering. Each appended entry is Merkle-hashed into a chain.
Database Design
Voter registration data lives in a PostgreSQL cluster with strict access controls, partitioned by jurisdiction. The voters table stores voter_id, eligibility_status, token_redeemed_at (null until voting), and nothing about ballot choices. The double-vote prevention uses a Redis distributed lock acquired when a token is redeemed, with a Postgres write as the durable record.
The encrypted ballot store is an append-only log (Apache Kafka with Tiered Storage, or a custom Merkle-tree-based store) where each entry is (sequence_number, encrypted_ballot, eligibility_signature, timestamp, merkle_hash). This log is the public bulletin board — a read-only replica is published to a publicly accessible endpoint. Tally results are stored separately in a write-once table, only populated after polls close and the tally ceremony runs.
API Design
POST /api/v1/auth/voter-login — authenticates voter and issues a session token (rate-limited, geo-restricted to expected polling regions).
POST /api/v1/ballots/token — redeems authenticated session for a one-time cryptographic eligibility token; idempotent (same token returned if called again before redemption).
POST /api/v1/votes/cast — submits encrypted ballot with eligibility token; returns {receipt_code, merkle_position} for verification.
GET /api/v1/bulletin-board/verify?receipt={code} — public endpoint returning the encrypted ballot entry and its Merkle proof.
Scaling & Bottlenecks
Election-day surge is predictable: auto-scaling groups for the Casting Service are pre-warmed 2 hours before polls open. The Authentication tier is the most resource-intensive (identity verification, HSM signing); horizontal scaling of HSM-backed signing nodes (CloudHSM clusters in multiple AZs) is planned for in capacity testing 30 days before the election. Load testing at 5x expected peak is mandatory by the system's operating procedures.
The double-vote prevention mechanism is a critical bottleneck: a distributed check-and-set must be atomic. Using Redis SETNX with Lua scripts provides atomic test-and-set; the Postgres write follows asynchronously as the durable record. If Redis becomes unavailable, the system falls back to Postgres-based pessimistic locking at reduced throughput rather than allowing potential double-votes.
Key Trade-offs
- Internet voting vs. kiosk-only: Internet voting maximizes accessibility but greatly expands the attack surface; kiosk-based deployment with air-gapped networks reduces risk but limits voter convenience.
- Anonymity vs. auditability: Perfect anonymity (votes cannot be traced to voters) is in tension with the ability to challenge specific ballots; blind signatures and mix-nets provide both properties cryptographically but increase system complexity.
- Real-time results vs. batch tallying: Publishing partial results during voting hours could influence remaining voters; batch tallying after polls close is standard but delays results.
- End-to-end verifiability complexity: Cryptographic receipts give voters proof their vote counted but require voter education and introduce complexity that can be exploited for vote-selling coercion if poorly designed.
GO DEEPER
Master this topic in our 12-week cohort
Our Advanced System Design cohort covers this and 11 other deep-dive topics with live sessions, assignments, and expert feedback.