system-design

Practice Problem: Design an Online Judge (LeetCode / HackerRank)

Prompt: Design a system where users submit code solutions to programming problems; the system runs the code against test cases in a sandbox, and returns pass/fail with time/memory usage. Attempt cold for 45 minutes first.

Tests: running untrusted code safely at scale, async job execution, resource limiting. Shares its core with the CI/CD platform.


Solution outline

1. Requirements

2. Estimation

Normal load modest, but contests cause huge spikes — thousands of submissions in the first minutes → bursty job load. Each submission runs code against many test cases (CPU-bound, seconds each).

3. High-level design — async sandboxed execution

🚨 Submission is asynchronous (don’t run code inline on the web request):

flowchart LR
    User -->|submit| API[Submission API]
    API --> Q[[Judge queue]]
    API --> DB[(Submission: PENDING)]
    Q --> Judge[Judge workers<br/>sandboxed executors]
    Judge -->|run vs test cases<br/>resource-limited| Sandbox[Isolated container/VM]
    Judge --> DB2[(Verdict + time/mem)]
    DB2 -.notify.-> User

API accepts the submission, stores it PENDING, enqueues a judge job, returns immediately. Judge workers pull jobs and execute the code in an isolated sandbox against the test cases, then record the verdict. Results push back to the user (poll/WebSocket).

4. Deep dives — the security core

🚨 Running untrusted code safely is the whole problem (same as CI/CD):

Other deep dives:

5. Trade-offs

| Decision | Chosen | Why | | — | — | — | | Execution | Async via queue + workers | Don’t run hostile code on web tier; absorb spikes | | Isolation | Ephemeral container/microVM per run | Untrusted code must not escape or leak | | Limits | CPU/mem/net/process caps + timeout | Stop infinite loops, fork bombs, abuse | | Contest load | Autoscale workers + fair scheduling | Handle spikes without starvation |

6. What a strong answer includes

Async job execution with a queue, and — the crux — ephemeral sandboxed execution with hard resource limits and no network/least privilege for untrusted code, plus autoscaling and fair scheduling for contest spikes, and deterministic time limits for fair verdicts. A weak answer runs submitted code directly on a server with no isolation — a catastrophic security hole.


Further reading