How do you build an exam timer students can't cheat?
By Saksham Jain ·
Make the server the source of truth for the deadline. Hold the session in Redis, write each answer there as it is selected, flush to the database periodically, and auto-submit when the server's deadline passes. The client clock is only a display, so changing the system clock or backgrounding the tab changes nothing.
From the production case study PS Classes.
Why can't the timer live in the browser?
A client-side countdown can be extended by editing the system clock, pausing a background tab or tampering with local state. Anything the client controls cannot be trusted for a deadline. The browser can display remaining time, but the server must decide when the attempt ends.
Why store the exam session in Redis?
With 500+ students starting a test series in the same slot, a primary-database round trip on every answer is too slow. Writing each answer to a Redis-held session on selection is sub-second. The session is flushed to MongoDB periodically, and the server auto-submits at the deadline.
How do you stop a double submit from two tabs?
Put a short-lived Redis lock on the attempt ID, SETNX-style. The first submit takes the lock and wins; the second is rejected as already processed. This is pessimistic by design: a submit happens once, so a few milliseconds of lock is cheaper than a double-counted attempt corrupting the rank.
How do you compute All-India Rank without rescanning every attempt?
Put submitted attempts on a RabbitMQ queue. A scoring worker consumes them, updates the score and percentile rollup incrementally, and writes results to Redis. Rank and chapter-wise analytics are then read from a fast cache instead of being recomputed on every result page view.