Skip to Content
Back to Projects
900+ Concurrent Users

LiveVote: Real-Time Polling Engine

Architecting a highly concurrent, zero-loss real-time voting infrastructure handling traffic surges without database locks.

Technologies Used

Node.jsFirebase FirestoreRedisNext.jsTypeScript

Scope & Context

Founding Engineer project targeting high concurrency, real-time sync, or custom system designs.

Codebase Link

Private repo · Available on request

The Problem

Standard polling applications often fail during live events due to massive database write contention. In a typical relational or simple document setup, having thousands of users vote within a short window causes single-document write locks (e.g., Firestore's strict limit of 1 write/second per document).

This contention depletes thread pools, causes connection timeouts, and drops critical vote transactions, leading to a frustrating user experience and inaccurate metrics during live interactive broadcasts.

The Solution & Architecture

I designed a decoupled buffer-and-process architecture to separate incoming HTTP traffic from database write cycles:

  • In-Memory Buffer (Redis): Incoming votes are immediately ingested into a memory-efficient Redis list acting as a FIFO queue, returning a 202 Accepted status to the user in <15ms.
  • Firestore Sharding: Instead of incrementing a single counter, I implemented a Distributed Counter Sharding pattern. Every poll counter is split across 20 distinct document shards.
  • Asynchronous Worker Nodes: A group of lightweight Node.js consumer daemons pull vote batches from the Redis queue and write updates to random shards in Firestore, avoiding database write contention.

Engineering Deep Dive

The toughest roadblock was dealing with uneven shard distribution (hotkey clustering). Under random shard assignment, statistical clustering led to certain shards receiving concurrent writes, re-triggering contention warnings.

To solve this, I replaced random selection with a consistent hashing algorithm. Using a custom distribution ring based on the voter's salted session ID, I ensured votes from different sessions mapped evenly to distinct shards.

Additionally, I built a scheduling service that runs every 5 seconds to query the shards, aggregate the numbers, and update a single materialized read-view document, ensuring clients can fetch clean poll totals with a single read operation instead of reading all shards on every page load.

Related Reading: For a deeper comparative analysis of backend JavaScript engines and why Node.js or Bun are suited for high-concurrency tasks, read my article: Node.js vs Bun vs Deno: The Ultimate JavaScript Runtime Comparison.

Quantifiable Metrics

1

900+ Connections

Processed 900+ concurrent connections in automated load testing without a single dropped packet.
2

12ms Latency

Reduced vote-absorption API latency from 1.8 seconds (direct write) to 12ms (Redis enqueue).
3

100% Write Success

Achieved 100% data write consistency without encountering Firestore transaction contention limits.
4

95% Cost Reduction

Decreased client database read costs by 95% using the materialized aggregation read-view.

Visual Showcase

Screenshots, dashboard metrics, and recorded event videos proving the system running in real-time.

LiveVote production dashboard showing attendee participation metrics.

LiveVote production dashboard showing attendee participation metrics.

Real-time voting queue and database write sharding visualizer.

Real-time voting queue and database write sharding visualizer.