Online coding judge inspired by LeetCode and Codeforces: submissions saved and queued per language, untrusted code run in throwaway container sandboxes with no network and fixed limits, hidden test cases in object storage, verdicts polled from a cache, live contest rankings in a sorted set, and judges scaled ahead of contests. A teaching design.
See why running untrusted code next to the website is the first thing to fix.
What was missing: Nothing yet.
Why that's risky: Submitted code is untrusted. An infinite loop ties up the server, a fork bomb takes it down, and code that reads the disk can leak the hidden test cases. Every page load waits behind running submissions.
What gets added: One server that serves problems and compiles and runs each submission on the same machine before replying.
Trade-offs: The simplest possible design. Isolation and capacity are both missing.
Take judging off the web tier and run every submission in an isolated sandbox.
What was missing: Untrusted code ran on the web server.
Why that's risky: Every problem page and every poll hits the databases, and hidden test cases are large files stored as rows.
What gets added: A submission service that saves each submission as queued and returns its id at once, a queue per language, and judge workers that run code in throwaway containers with no network and fixed CPU, memory and time limits. Clients poll for the verdict.
Trade-offs: Users wait a few seconds for a verdict instead of holding a connection open, in exchange for a website that never stalls.
Serve the read-heavy pages cheaply, and keep big test files out of the database.
What was missing: Problem pages, verdict polling and test case reads all hit the databases.
Why that's risky: Contests have no live ranking, and nothing stops one user from flooding the judges.
What gets added: A CDN and a cache for problem pages, hidden test cases as files in object storage that judges cache locally, and a status service that answers polling from a cache the judges write to.
Trade-offs: Test case files are cached on judges, so an edited test needs a version bump to take effect.
Rank a live contest as verdicts arrive.
What was missing: No live contest ranking.
Why that's risky: One load balancer, and a single user can still submit as fast as they like.
What gets added: A sorted set per live contest, ordered by problems solved and then penalty time, updated by the judges as each accepted verdict lands. More judges for contest load.
Trade-offs: Rankings during the contest are provisional. Final standings are recomputed from the submissions database after hidden re-judging.
Survive the last ten minutes of a big contest.
What was missing: No per-user submission limit, no spare load balancer, and no view of queue wait.
Why that's risky: Remaining risk is low. A very slow language can still build a backlog. Per-language queues keep it from delaying others.
What gets added: A rate limiter (a few submissions per user per minute), a second load balancer, judges that scale out on queue depth before a contest starts, a replicated submissions database, and monitoring of queue wait per language and verdict latency.
Trade-offs: Judges are scaled up ahead of scheduled contests rather than purely on demand, since containers take seconds to start.
You're in the middle of an interview session. Leaving now will end your current attempt.
Explore concept overviews, real-system examples, key tradeoffs, and interview talking points for each roadmap section.
You've conquered this phase. These are the skills you now own: