Skip to content

Best Practices

The principles this codebase actually follows — each one earned by a specific incident or constraint documented elsewhere on this site. Useful both as house style and as interview material, since every entry comes with a concrete story.

Design around the platform's constraints, early

The 20k-file Pages limit was designed around at ~1,200 questions, not discovered at 19,999 (Question Bank). Free-tier AI flakiness was answered with a nine-provider chain before an exam-day outage, after the first cascading failures (AI Pipeline). The pattern: read the platform's limits page first, then architect.

One implementation per concern

One markdown parser, one AI client, one judging path, one "where is the website" resolver. Every duplicated implementation in this project's history drifted and caused a bug — the 34-duplicate incident was a drifted duplicate of the lint rules (Tools Overview). If two things must agree, make them one thing, or make their agreement a tested contract (the twice-implemented grading contracts are the deliberate exception, and they carry tests).

Turn every incident into a gate

Compile timeout → banned include in lint. Wrong reference solution → mandatory verify_solution.py. Duplicate questions → live-content collision checks. Missing hints → pipeline validation. The instance gets fixed once; the class gets fixed forever. Corollary: a fix without a gate is half a fix.

Deterministic first, AI second

Aptitude and SQL decide correctness without a model and use AI only to explain (Aptitude, SQL). Where AI must judge (free-text CS answers), it's fenced: rubric-bound, JSON-coerced, chain-backed, honest-stubbed. Never let a model own a verdict that arithmetic can own.

Fail loudly, degrade honestly

The echo stub announces itself instead of imitating a model. Missing tokens 500 with a message instead of rendering an empty pane. Judge unavailability is a named verdict, not a hang. Silent degradation is how the reminder bug lived so long — the Worker "worked," it just skipped people (Scheduling).

Server timestamps own time; preconditions own concurrency

Exam timers derive from Firestore startedAt, never client state (OA Simulator). Workers claim work with updateTime/create preconditions instead of locks (Workers). Both replace "hope the client/cron behaves" with an invariant the database enforces.

Measure before optimizing — and accept surprising answers

Judge concurrency = 1 beat parallelism on the single-core VM. Virtualization beat memoization for long lists. The 1,153→855KB bundle drop came from measuring what actually shipped, not guessing (Performance).

Mirrored data must name its freshness mechanism

The email-sync bug in one sentence: a field copied once is a field that rots. Every mirror now answers "what keeps this fresh?" at the moment it's introduced (Authentication).

Scope honestly

Anti-cheat discourages, it doesn't proctor — and says so. problemStats documents the write-integrity limitation it accepts and the escalation path if stakes rise (Database). Claiming less than the system does is how the claims stay true.

Secrets: minimum scope, server-side, rotatable

The token incident produced the rule set: fine-grained read-only scope, Pages/Worker env only, rotation without redeploy, loud failure on absence (Docy). And the build-time/runtime split is absolute: VITE_* is public, Function env is secret.

Ediky Workflow — internal engineering documentation.