Four-person database-systems course project

Chore Tracker API

A backend for roommates to coordinate chores and split shared bills.

  • FastAPI
  • Python
  • PostgreSQL
  • SQLAlchemy Core
  • Docker
  • Supabase CLI
  • Swagger
Entity relationship diagram for the Chore Tracker database
five tables connect roommates, work, and shared expenses
the short version:
1,000,025
rows in the performance dataset
the backend system

two roommate problems sharing one relational model

The API handles household work and household money: chores can be assigned and moved through statuses, while bills are split into per-roommate shares with individual payment states.

There is intentionally no frontend. FastAPI's Swagger UI and documented curl workflows are the product surface for this four-person database-systems project.

what the API supports

chores, assignments, bills, and payment state

01

Roommate records

Create, list, and remove people who participate in assignments and bill splits.

02

Chore lifecycle

Create chores, assign them, update priorities and statuses, and inspect recent history.

03

Shared bills

Create a bill, split it across current roommates, edit its metadata, and update each person's payment status.

04

Administrative reset

A protected reset endpoint and synthetic data make repeatable grading and performance experiments possible.

how it works

from synthetic scale to an evidence-backed index

  1. 01

    Generate realistic scale

    A Faker and NumPy script creates weighted roommate, chore, assignment, bill, and payment-share data totaling 1,000,025 rows.

  2. 02

    Create the local database

    I set up a Dockerized PostgreSQL 15 environment through the Supabase CLI, using its local port 54322 for the benchmark.

  3. 03

    Measure the endpoints

    Swagger UI captures end-to-end API latency for the full request path, including application and serialization work.

  4. 04

    Inspect the SQL

    EXPLAIN and EXPLAIN ANALYZE isolate database execution and reveal sequential scans in the three slowest queries.

  5. 05

    Design targeted indexes

    Four indexes match the observed filters, joins, and ordering instead of indexing columns speculatively.

  6. 06

    Re-run the plans

    The query planner switches to index scans, and database execution time is measured again against the same local dataset.

  7. 07

    Separate the two clocks

    The final analysis compares database execution time with end-to-end API latency, avoiding the false claim that SQL time explains the whole request.

under the hood

the API and database layers

FastAPI + Pydantic

Defines 16+ documented REST endpoints, request schemas, enums, and a consistent validation-error response.

SQLAlchemy Core

Manages Postgres connections while the routers issue raw parameterized SQL rather than ORM model calls.

PostgreSQL

Stores five related tables: roommate, chore, chore_assignment, bill, and bill_list.

Docker + Supabase CLI

I used the Supabase CLI to provision the Docker-backed local PostgreSQL environment for the million-row benchmark. The project has no custom Dockerfile or Compose file, and the API itself was not containerized for deployment.

Render

Hosts the FastAPI service and its Swagger documentation. Docker was used locally for the database benchmark, not for production deployment.

Swagger + curl

Replaces a frontend with an inspectable API contract and two documented manual user workflows.

Faker + EXPLAIN ANALYZE

Creates realistic scale, exposes sequential scans, and verifies index-driven plan changes.

data model

Five tables, two household problems

Roommates and chores meet through chore assignments; roommates and bills meet through bill-list shares. I drew the ER diagram and helped establish the original schema and SQLAlchemy connection pattern.

Five-table ER diagram
the system on one page
business logic

Splitting a bill without losing cents

I built the original bill endpoints and even-split flow, including validation when no roommates exist. A teammate later extended that foundation with the exact remainder-cent distribution used in the final code.

performance

Measure, index, measure again

I generated a weighted synthetic dataset of 1,000,025 rows and set up a local Dockerized PostgreSQL environment through the Supabase CLI so network latency would not distort the database benchmark. I timed the API through Swagger, then ran EXPLAIN and EXPLAIN ANALYZE on the three slowest queries.

Four targeted indexes moved the identified plans away from sequential scans. For roommate assignments, raw database execution time fell from 86.427 ms to 5.088 ms. End-to-end API latency remained higher because serialization, application work, and transport also contributed.

concurrency

Choosing isolation by scenario

I mapped two concurrency scenarios: bill creation racing with roommate deletion, and two roommates claiming the same chore.

The designs use SERIALIZABLE for the dependent multi-write bill flow and READ COMMITTED plus a unique constraint for chore claims. They were design analyses rather than implemented isolation controls.

my contribution

the database and API areas I worked on

I bootstrapped the connection/schema foundation, originated the main bill endpoints, added early chore-assignment behavior, drew the ER diagram, generated the million-row dataset, and owned the performance investigation.

  • Established the SQLAlchemy connection pattern and first five-table schema.
  • Built the original bill creation/list/assignment/payment/update endpoints and even-split foundation.
  • Added duplicate-assignment validation, status updates, and a correct upper bound to 30-day history.
  • Designed four indexes after reading real sequential-scan plans, then re-measured database and endpoint time separately.
  • Authored two concurrency scenarios; these are design analyses, not isolation controls implemented in the final API.
database-course process

design, peer review, manual workflows, then performance

The team worked from user stories to ER/API specs, responded to named peer reviews, ran two structured curl-based user workflows against the live service, and finished with concurrency and performance analyses. Pytest was listed but no automated suite was implemented.

model

Draw cardinalities and define the schema before endpoint work.

spec

Document request/response contracts and exception behavior.

review

Accept, reject, or defer peer feedback with written rationale.

measure

Seed realistic scale, inspect query plans, add targeted indexes, and re-test.

what happened

results, with context

1,000,025

rows tested

Synthetic but deliberately shaped across all five tables.

4

indexes

Added after reading the actual query plans.

16+

endpoints

Chores, assignments, roommates, bills, and payment states.

looking back...

The project taught me to separate database execution time from total API latency and to let observed plans, rather than intuition, drive indexes. Pagination and implemented transaction controls would be the next engineering steps.