Nobody has started this yet — be first.
Business impact
This service's entire memory-bounding guarantee (the README's "Backpressure, for real" section) rests on the assumption that every queued event record is roughly the same, small size. Right now EventIn.payload accepts a JSON object of any size at all, so a single client sending one event with a multi-megabyte payload can blow that assumption open — the per-event size limit the codebase already defines is currently not enforced.
Problem
EventIn.payload accepts any JSON object with no size check. app/schemas.py already defines MAX_PAYLOAD_BYTES = 16 * 1024 and a _enforce_payload_size field validator wired onto EventIn.payload, but the validator's body is a no-op stub that returns the value unchanged no matter how large it is.
Current behavior
EventIn._enforce_payload_size is a stub that returns value unchanged regardless of size; constructing an EventIn with a payload well over 16KB once serialized raises nothing at all.
Expected behavior
An event whose payload, once JSON-serialized, exceeds MAX_PAYLOAD_BYTES is rejected at the API boundary with a 422, before it ever reaches the queue; an empty payload is always accepted.
Steps to reproduce
cd fastapi/ingest_service && .venv/bin/python -c "from app.schemas import EventIn; EventIn(device_id='d1', event_type='t', payload={'blob': 'x' * 20000})"Why this matters
This whole service's headline design property is "memory is bounded by queue_max_size * bytes-per-record, full stop" — that arithmetic implicitly assumes each queued record is roughly the same, small size. A single client sending one event with a multi-megabyte payload blows that assumption open; the size bound has to be enforced per event, at the API boundary, for the queue-level bound to mean anything.
Suggested approach
Look at EventIn._enforce_payload_size in app/schemas.py — it's already registered as a @field_validator("payload"), it just needs a real body. You'll need some way to measure the serialized size of a dict (think about what payload becomes on the wire, and what standard library tool turns a dict into that representation so you can measure its length).
Acceptance criteria
Verification
pytest practice_tickets/tests/test_ticket_06_payload_size_limit.py -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
Sign in to create it automatically, or do it yourself:
$git checkout -b feat/payload-size-limitFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/payload-size-limitSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inhttp://localhost:8000localhost:5432curl localhost:8000/healthzcurl localhost:8000/readyzWork the tickets in practice_tickets/tickets/ (ordered easy → hard); each names one dedicated test in practice_tickets/tests/:
pytest practice_tickets/tests/test_ticket_01_persisted_count.py -v # a single ticket
./practice_tickets/run_tickets.sh # all 20, clean pass/fail summary
TICKET-17 needs a real Postgres to run at all (it checks which column a value lands in, which no fake/in-memory DB backend can meaningfully verify) — set TEST_DATABASE_URL=postgresql://<you>@localhost/ingest_test before running it or the full suite; without it, that one test is skipped, not failed.
Level 2
Implement a feature
Extend the system within its own patterns.