Extend existing code · 60 minutes · use any AI tool

Practice round 1: Rate limits for a small API

Extend a small currency conversion service with per key rate limiting. Reading a service you did not write, settling the open questions in a brief, and testing behaviour over time.

Time
60 minutes
Task
Extend existing code
Language
Python 3.10 or newer, standard library only
In the zip
9 files of existing code, 12 visible tests, 8 extra checks

Download ratelimit.zip 13.3 KB

The brief

Rates is a small currency conversion API. A few customers have started hammering POST /v1/convert from scripts, and last week one of them slowed the service down for everyone.

Add rate limiting to the API. Each API key may make at most its plan's number of requests per minute (the plans are in service/config.py). Callers without a key are limited by their client address, at the anonymous plan's rate. When a caller is over the limit, answer 429 and tell them when to try again.

Keep the existing behaviour working. You decide the details the brief leaves open; write down the decisions you made in NOTES.md as you go, as you would in a pull request description.

Ground rules

  • Set a timer for 60 minutes before you open your AI tool, and stop when it rings.
  • Use your own agent (Claude Code, Codex, Cursor or any other). Work the way you would at work.
  • Python 3.10 or newer, standard library only. No installs.
  • Do not open the checks folder until your timer has stopped.

Running it

python -m unittest

Some tests in tests/test_rate_limit.py fail until the work is done. tests/test_handlers.py passes today and should keep passing.

To try the service by hand: python server.py, then use the curl lines at the top of server.py.

The existing code

  • service/app.py routing, API key checks and the access log
  • service/auth.py API keys and accounts
  • service/config.py plans, keys and deployment settings
  • service/clock.py time, with a fake clock for tests
  • service/handlers.py the endpoints
  • service/http.py request and response types
  • service/netutil.py network helpers
  • server.py a local server for manual tries

When the timer stops

Run the extra checks first. Then start a new session of your agent in the same folder and paste the review prompt from REVIEW.md, filling in the path to the transcript of the session you just finished. The full rubric descriptions are in the file; this is the shape of the prompt:

You are reviewing my coding session from a 60 minute practice round. The brief is in README.md. Read the
session transcript at <path to this session's transcript> and judge how I worked, not how the code looks.

For each of the five dimensions below:
1. Quote two or three exact lines from my prompts, or name exact actions (a rejected edit, a command I ran, a
   file I opened), as evidence. Give the time or position in the transcript for each.
2. Say whether the evidence reads as strong, middling or weak, using the descriptions below, and why.
3. If the transcript does not show enough to judge, say "not enough evidence" instead of guessing.

1. Breaking the problem down: Turning a loose brief into a plan you own, then handing the AI one well defined step at a time.
2. Context given to the AI: Supplying the facts the AI cannot guess: the constraint in a config file, the rule in a document, how the system is deployed, the helper that already exists.
3. Verifying output: Checking that what the AI produced is right before relying on it.
4. Correcting the AI: Noticing when the AI goes wrong, stopping it, and steering it back precisely, or doing the small fix by hand.
5. Tradeoff reasoning: Naming the options, choosing one for a reason tied to this system, and saying what was given up.

Then list the three moments that most helped me and the three that most cost me, each with its quote, and one
thing to do differently in the next round. Do not invent quotes. If you cannot find a line, say so. Do not give
an overall score.

For counts such as prompts, rejected edits and test runs, drop the transcript on the transcript stats tool. It reads the file in your browser and uploads nothing.

Every file in the zip
  • openbook_ratelimit/README.md
  • openbook_ratelimit/REVIEW.md
  • openbook_ratelimit/checks/__init__.py
  • openbook_ratelimit/checks/check_rate_limit.py
  • openbook_ratelimit/server.py
  • openbook_ratelimit/service/__init__.py
  • openbook_ratelimit/service/app.py
  • openbook_ratelimit/service/auth.py
  • openbook_ratelimit/service/clock.py
  • openbook_ratelimit/service/config.py
  • openbook_ratelimit/service/handlers.py
  • openbook_ratelimit/service/http.py
  • openbook_ratelimit/service/netutil.py
  • openbook_ratelimit/tests/__init__.py
  • openbook_ratelimit/tests/helpers.py
  • openbook_ratelimit/tests/test_handlers.py
  • openbook_ratelimit/tests/test_rate_limit.py