-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
fastapi migration
Goal: Migrate to FastAPI for better performance, strong typing, data validation, and improved developer ergonomics. We prioritized high-traffic endpoints first and are now migrating the remainder (as of Feb 2026). Later we will migrate html pages.
When developing and testing locally, be aware of which port serves which version:
| Port | Serves | Notes |
|---|---|---|
localhost:8080 |
web.py (legacy) | Will eventually proxy to FastAPI |
localhost:18080 |
FastAPI | Use for testing new endpoints |
To test your new FastAPI endpoint:
- Swagger UI: Visit http://localhost:18080/docs to interact with and test your endpoint payloads.
-
Direct testing: Hit
http://localhost:18080/<your-endpoint>directly with curl or your API client.
Once we fully delete the old web.py endpoints, port 8080 will proxy to 18080 — but this only happens once DEPRECATED_PATHS in deprecated_handler.py is updated to include the deprecated path.
- Create: Build the new FastAPI endpoint, ensuring it matches existing functionality.
-
Stage: Deploy to the testing environment (available at
_fast/<endpoint>). - Route (Testing): Update testing NGINX config to point to the new endpoint.
- Verify: Test edge cases, comparing testing traffic to production.
-
Deploy: Merge to
master, updateolsystemrouting, and wait for deployment. -
Cleanup: Remove old endpoints, add local redirects (
deprecated_urls), and merge.
This is a short guide for migrating a remaining web.py endpoint to FastAPI.
- Find the endpoint in the codebase and read it carefully.
- Identify all input parameters (path, query, body) and their types.
- Understand the output format (JSON shape, status codes, error cases).
- Note any authentication requirements (required login vs. optional user).
- Place the new endpoint in the appropriate file under
openlibrary/fastapi/. Stubs already exist for most areas that need migration. - Follow the patterns established in the existing FastAPI files. Key references:
-
Auth: See
auth.pyfor how to require authentication or get an optional current user.-
public_my_books.pyis an example of an option user andyearly_reading_goals.pyis an example of a required user. -
get_current_user()is only needed if you want an infogami User object with special functions attached. Generally you won't need this unless it was already used.
-
- Validation: Use Pydantic models for request bodies and response shapes. Declare path/query parameter types explicitly so FastAPI validates them automatically.
- Business logic: Keep endpoints thin — extract logic into helpers or static methods rather than embedding it in the route handler.
-
Auth: See
- Refer to the FastAPI skill and docs and existing endpoints in the codebase for best practices (e.g.,
Annotatedfor dependencies and path params).
Create a temporary bash script (e.g., test_<endpoint>_compare.sh) to verify the old and new endpoints behave identically:
- Call the same request against both:
-
web.py (legacy) →
localhost:8080 -
FastAPI (new) →
localhost:18080
-
web.py (legacy) →
- Compare response bodies — they should be identical for success cases.
- Minor differences in status codes or validation error messages are acceptable.
- Cover the happy path and important edge cases.
#!/usr/bin/env bash
# Temporary comparison script — delete before merging.
ENDPOINT="/api/example.json?param=value"
OLD=$(curl -s "http://localhost:8080${ENDPOINT}")
NEW=$(curl -s "http://localhost:18080${ENDPOINT}")
if [ "$OLD" = "$NEW" ]; then
echo "✅ Outputs match"
else
echo "❌ Outputs differ"
diff <(echo "$OLD" | python3 -m json.tool) <(echo "$NEW" | python3 -m json.tool)
fiNote: This script is for local comparison only. We will delete it before merging.
Once the FastAPI endpoint is working, mark the old web.py endpoint as deprecated using the existing pattern:
Why separate PRs? We generally keep the old endpoint alive until the new one is verified in production. This way, if something breaks, we can quickly revert the routing to point back at the old web.py version without needing another PR. Only after the new endpoint has been stable in production do we delete the old one.
@deprecated("migrated to fastapi")Do not delete the old endpoint yet. Removal will happen in a separate PR once we are confident the new endpoint is stable in production.