Course Intro + Pawtograder Architecture I

Reminders
- RELEASED: The Ticket Hunt. Due Wed Sep 16
- RELEASED: Onboarding: Gradebook Column Groups. Due Thu Sep 24
- RELEASED: Project Bids. Due Thu Sep 17
CS 4535: Software Design & Delivery
Course Intro + Pawtograder Architecture I
©2026 Jonathan Bell, CC-BY-SA
Learning Objectives
After this session, you'll be able to:
- Describe the major components of the Pawtograder stack and how one request flows through them
- Map the project slate onto areas of the system
- State what you need working before Thursday
Notice what is not on that list. You don't need to understand any of this deeply today — "describe" and "map" are the verbs. Every box on today's diagrams gets its own session later.
Who's In the Room
It's a small room. By December you'll have reviewed each other's code. Let's start there.
Tell us:
- Your name, and something you did over the summer
- What you want out of this Fall — in this course, and after it
- Your relationship with AI tooling: how you use it, how you want to use it, and how you don't
I'll go first.
On question 3: there is no AI restriction in this course. Use anything. I'm asking because nobody has this figured out, and a room's worth of honest answers is a better starting point than a policy.
Grading: Four Bands, No Points
| Band | Means | Letter |
|---|---|---|
| Pass | Trusted to contribute under review | B |
| Credit | Trusted to exercise judgment, not just execute | A− |
| Distinction | Trusted to own what ships (four of five) | A |
| High Distinction | Trusted to extend the system | A, and a letter with something in it |
Each band is a published list of things you've demonstrably done. Every band requires the one below it. You declare which you're working toward on Oct 1, and you can change it either way until Dec 3.
There's no way to reach an A while being weak at one of the eight outcomes.
What That Means In Practice
Almost nothing here is a submission. You're graded from the things professional work produces anyway: pull requests, review threads, commit history, design notes, postmortems, dashboards.
In December you write a Learning Summary Report: the band you're claiming, and a link to the artifact that satisfies each requirement. I verify the claim rather than re-grading the work, because the work was already reviewed when it happened.
Which makes the report quick to write if you did the work, and unwritable if you didn't.
Two Phases, Two Rhythms
Weeks 1–3: Onboarding
- Lecture every session
- The Ticket Hunt: file two, triage two. Due 9/16
- Column Groups: everyone builds the same feature, alone. Due 9/24
- Bids due 9/17 · teams announced 9/24
Weeks 4–14: Studio
- Mon: standup + clinic
- Wed: tech talk or student presentations
- Thu: team work, game day, or demo day
- Demos every two weeks. Game days unannounced.
- You will hold two roles: a project team and a cross-project function
Feature freeze is Mon Nov 23. Weeks 13–14 are hardening, documentation, and ops playbooks for the January handoff. Nothing new lands after the freeze.
Before the Diagrams: The Vocabulary
Cloud platforms give you a standard set of parts. Every architecture diagram you'll see this semester is made of these six, and nothing else.
Database
Structured data you can query
ours: Postgres
Object storage
Files too big for a database
ours: Supabase Storage
Queues and event buses
Work that waits its turn
ours: pgmq, EventBridge
Cache
A fast copy of hot data
ours: Upstash Redis
API gateway
One front door, with a lock
ours: the Supabase gateway
Observability
Logs, metrics, traces
ours: Sentry, Prometheus
Plus one more: serverless compute — code that runs on demand and then disappears. Ours are the edge functions.
Every one of these six gets its own session — schedule at the end of today
What a Database Actually Is
Somewhere to put data that survives a restart — and, more importantly, somewhere you can ask questions of it. The right kind depends entirely on the questions.
Relational (SQL)
Rows, columns, and relationships between tables. Powerful queries, real transactions, rigid schema.
Postgres, MySQL
SELECT s.*, a.title
FROM submissions s
JOIN assignments a
ON s.assignment_id = a.id
WHERE s.student_id = ?
Document (NoSQL)
JSON-shaped blobs. Flexible schema, fast to start, weak at questions that span records.
MongoDB, Firestore
{
student: "alice",
scores: [85, 92, 78]
}
Key-value
Fetch by key. Blazing fast, no queries at all.
Redis, DynamoDB
GET user:12345
SET session:abc {...}
Why Postgres, reason 1: our questions are relational
"Every submission by this student, across every assignment, with the assignment title."
That's a join, and joins are what SQL is for.
Reason 2: it can enforce the rules itself
Postgres has row-level security — a policy attached to the table.
"A student sees only their own submissions" becomes a property of the rows, not something every query has to remember.
Reason 2 is the bigger one, and it shapes almost everything else you'll see today.
Full session: Mon 9/14 — Architecture II: Supabase, RLS & Student-Data Privacy
Webhooks, Queues, and Why There Is an EventBridge
A webhook is just an HTTP POST that someone else sends you, when something happens on their side. No magic. GitHub calls us; we didn't ask.
A queue or event bus sits in the middle and holds the message. The sender is done once it's accepted; delivery is somebody else's problem.
So: if we're deploying when a student pushes, a raw webhook is lost forever. GitHub gives up quickly. EventBridge keeps trying long after GitHub would have stopped and we pay for the privilege.
Comes back on Thu 9/24 (Monitoring) and Thu 10/22 (Game Day 1)
Pawtograder Has One Architectural Thesis
1. The database is the application. The logic lives in the database, and the database enforces security on the data.
2. We want the application to be sequentially consistent. One coherent order of events. What you just did is what you see.
3. Consistency is hard when you have to wait. So everything crossing the boundary gets a queue, in both directions. The outside world is allowed to be on fire — and so are we.
Every diagram for the rest of today is one of these three claims.
The Stack: Everything In Play
How They Talk
rpc()— most reads and writes- Realtime broadcast — nothing polls
functions.invoke()- service-role available, prefer user-role
pg_cron + pg_net— the database calls out- webhook, via EventBridge
- dispatch
grade.yml - OIDC-authenticated callback
Left off on purpose: Discord and Chime hang off the edge functions, Sentry collects exceptions from both tiers, Prometheus scrapes the functions.
The Database Is the Application
Authorization, business logic, queueing, scheduling and fan-out all live in Postgres. Not in the app.
Full session: Mon 9/14 — Architecture II: Supabase, RLS & Student-Data Privacy
Consistency Is Easy Until You Have To Wait
Block on the outside world
Commit, then enqueue
The transaction only depends on Postgres. Postgres is up, so we are up — and the work that needs GitHub happens whenever GitHub comes back.
GitHub had a worldwide outage on August 17. Grading kept queueing.
Queues, retries and dead letters in depth: Thu 9/24 — Monitoring & Incident Response
And We Are Allowed To Be On Fire Too
The same trick, pointed inward. Nothing outside should have to wait on us either.
For machines: a durable buffer
GitHub's webhooks land on an event bus, never on us directly.
- Buffers and retries with backoff
- Dead-letter queue for what still fails
- Durable audit trail, and replay
- Smooths a burst of pushes into a rate we can take
We can be down for a deploy, a migration, or a bad afternoon. The events wait.
For humans: an honest status page
A real page, served instead of the app.
HTTP 503with aRetry-Afterheader- Title, message and an ETA, set per window
- Refreshes itself, so nobody sits reloading
- Runs on its own replicas — it survives what took the app down
Users find out what happened and when we're back.
And we choose honest downtime over a half-working app: a read-only database is "unavailable, but unpredictably so."
Planned windows and rollback: Thu 9/17 · incident response: Thu 9/24
Sequence: How Autograding Works
CI in depth: Wed 9/23 · what it tests: Thu 9/24
Sequence: How a Gradebook Cell Gets Its Value
Queues, retries and dead letters again on Thu 9/24 — Monitoring
Data Access: Prefer RPCs
For data operations, reach for a Postgres RPC before a server action or an edge function.
RPC in Postgres
- Runs next to the data
- Authorization already applies
- One round trip
- The default for reads and writes
Edge function
- For integrations that call out: GitHub, Discord, AWS
- Not a general data path
- Deno, so no
@/alias and no Node imports
Types come from the schema. After a migration, run npm run client-local — never hand-edit the generated types.
Today Is the Map. The Detail Comes Later.
| What you saw today | Where it gets a whole session |
|---|---|
| Databases, RLS, student-data privacy | Mon 9/14 — Architecture II |
| The frontend: App Router, types, TableController | Wed 9/16 — Architecture III: The Client |
| Migrations, down paths, rollback | Thu 9/17 — Architecture IV: Deployment |
| CI/CD, feature flags, dark launches, trunk-based development | Wed 9/23 — Software Processes & Continuous Delivery |
| E2E and visual acceptance testing | Thu 9/24 — Testing |
| IaC, drift, Sentry/Grafana, incident response | Thu 10/1 — Tech Talk: Operations |
| Agents, context, sub-agents | Wed 10/7 — Tech Talk: Agents & Workflows |
| Risk registers, release readiness | Wed 11/18 — Tech Talk: Risk & Release Readiness |
| All of it, under time pressure | Game days — 10/22, 11/5, 11/19 |
Today's only job is that the picture makes sense. If you can point at a box and say roughly what it does, you're exactly where you should be.
Complexity Is Not Evenly Distributed

Seven Projects, Seven Parts of the System
| Project | Where it lives | What you'd be doing |
|---|---|---|
| Usability Strike Force | app/, components/ | Studies with real users, then shipping the redesign |
| Accessibility Strike Force | student pages, tools/a11y-judge/ | WCAG AA against real screen readers, then fixing what fails |
| Office Hours Reconceptualization | help queue, Realtime, Chime | Full product redesign, research through deploy |
| Docusaurus Integration | plugins/, public APIs | Schedule sync, embedded polls, search across two ecosystems |
| Paper Exam Generation & Grading | mostly new code | Variant generation, barcodes, scan ingest, OCR, grader UX |
| GitHub → Forgejo Migration | GitHub App, repo automation, CI | Provisioning, permissions, a migration path for live courses |
| Coder Workspaces Integration | auth, provisioning, grading actions | SSO and one-click cloud dev environments |
Every project spans the full lifecycle. None of them is only frontend or only backend.
What Happens Next
- Wed Sep 16 — Ticket hunt due. The pool you build is the pool we all draw from.
- Thu Sep 17 — Project bids due. Ranked preferences across the slate.
- Thu Sep 24 — Teams announced. Column groups due.
- Mon Sep 28 — Studio kickoff: charters, backlog, estimation.
- Thu Oct 1 — Declare your target band.
Between now and 9/17 you'll have run the app locally, filed a ticket or two from the hunt, and read code in at least two of those seven areas. Bid on the basis of that, not on the basis of this slide.
Before Thursday
Come to Thursday ready to get Pawtograder running.
- Bring a laptop with Node 22 (use
nvm) and Docker installed - A fresh clone of
pawtograder/platformif you get to it —mainhas moved since the application - You don't have to have it working by then. Thursday is when we do that part together
- If you do get a head start, click through the app as a user and note one thing that's wrong
- Being stuck is a fine outcome, being stuck silently is not
Thursday is a working session, not a lecture. Whatever is already installed when you sit down is time you get back for code.
Key Takeaways
- The database is the application. The logic lives there, and it enforces security on the data.
- We want sequential consistency, so nothing waits on anyone else. Commit what we own, queue what leaves the building, buffer what arrives — and when we're down, say so honestly.
- Complexity is concentrated, and the debt is not a secret. Working well inside it is the skill this course grades.
Thursday: get it running, together. Then ship something.
Up Next
Thu Sep 10 — Working Session: Local Dev & the Contribution Workflow
Today was the map. Tomorrow you get the keys: the app running locally, and a first ticket claimed.
Before then:
- The Ticket Hunt — due Wed Sep 16
- Onboarding: Gradebook Column Groups — due Thu Sep 24
- Project Bids — due Thu Sep 17