Work / Learning Platform / Architecture
Learning Platform architecture
A website and one API, both on Vercel. The API keeps accounts and progress in Postgres, and reads every lesson from the instructor's GitHub repo each time a student opens it. No bill is recorded anywhere.
last verified 2026-10-30
Known cost a month
$0–20
Vercel Hobby is free, Pro is $20 a seat. Which plan runs, and the database host, are not recorded.
What makes cost grow
Lesson views
Each view makes one GitHub call per slide or phase, with no cache. Function time, database size and email also grow.
Second limit
100 / 15 min
Requests per address. A fast student or a class behind one address can get 429s.
How it fits together
Pick something a user does to see its path and what it costs.
No bill read
one GitHub call per slide or phase, on every view
- The browser asks the API for the lesson.
- The API reads the lesson list from Postgres.
- For each slide and phase it fetches the file from GitHub, all at once. Nothing is cached.
- A missing file comes back empty. Any other GitHub error fails the whole lesson.
- The text goes to the browser. It is never stored in Postgres.
Cost
Every number says where it came from.
| Service | Pays for | Today | Grows with | Basis |
|---|---|---|---|---|
| Website | Next.js 16, the student and instructor screens | Not read | Page views and build minutes | Not known |
| API | NestJS and GraphQL, one serverless function · 30 s max | $0 on Hobby, $20 a seat on Pro; plan not recorded | Function time: every request, every lesson read | Statedprevious wiki/concepts/architecture.md; no bill read |
| Postgres | Accounts, enrolments, progress, answers, course metadata | Not read | Students, answers, database size | Not known |
| Google and GitHub sign-in | Optional sign-in with a provider | $0 (free tiers) | Nothing | Statedprevious wiki/concepts/architecture.md; no console read |
What breaks when something fails
| If this fails | The user sees | Their data | Basis |
|---|---|---|---|
| Website | No site. Nothing else is affected. | Safe, held by the API and Postgres | AssumedThe website holds no data of its own; apps/website/vercel.json |
| API | Sign-in, lessons and answers all stop. A failed start is retried on the next request. | Safe in Postgres | In codeapps/server/api/index.ts ensureReady; apps/server/vercel.json maxDuration 30 |
| GitHub | Lessons open without their text, or the page errors if GitHub answers with a failure other than 'not found'. A sync fails and shows 'Sync failed'. | Content is safe in the repo. Metadata stays in Postgres. | In codeapps/server/src/lib/git/git.service.ts fetchContentBase64; curriculum.service.ts runSync |
Where the data goes
| Lesson text, slides, questions, code | The instructor's GitHub repo. Read live, never stored. |
| Email addresses | Sent to AWS SES for each email |
| Backups | Provider snapshots; no backup was checked |
What we do not know yet
- The real monthly bill: no Vercel, database or SES cost is recorded.
- Which Postgres host holds production. The runbooks name Supabase and Neon; .context/ops/release.yml says provider null.
- Which Vercel plan runs. vercel.json asks for a 30 s limit, but the runbook says Hobby is capped at 10 s.
- The wiki and runbook still say lesson text is cloned to /tmp and lost on a cold start, with task 5.10 pending. The code now reads each file through GitHub's API and has no clone. The docs are out of date.
- Whether SES is out of its sandbox. This decides whether email verification can be turned on.
- A reset email can fail with no sign to the user, and no alert exists. Error tracking was skipped (task 5.6); only Vercel logs.
- How many users exist. No count or traffic figure is recorded, so no growth chart is drawn.
- No test suite, by decision. Nothing checks the flows above.
- Whether backups are on and have been restored. The runbook asks for a drill each quarter; none is recorded.