Work
A small serverless platform, and its sharp edges
React, FastAPI on Lambda, and a single-table DynamoDB store running a handful of private apps. Mostly interesting for the things that were hard to debug.
A private multi-app platform: a React SPA on S3 and CloudFront, a FastAPI backend on Lambda behind an HTTP API, and one generic DynamoDB table. Built so that adding a feature needs a new key prefix, not a migration.
The design decision that paid off
A single generic table. Items are pk = TOOL#<tool_id>, sk = ITEM#<uuid>
plus a free-form data map. New features never need a schema or table change —
just a new tool id string. Seven features later, there has still been no
migration.
The authorisation design
Two independent checks that answer different questions, deliberately not collapsed into one:
- Which section may see this tool at all. The tool name arrives from the URL and the store returns everything under that key, so every request resolves its tool to an owning section and callers outside it get a 404, not a 403 — so neither section can probe the other’s shape.
- Which items within a tool the caller sees. Private tools force an owner filter server-side regardless of what the client asks for, because the frontend is not a trustworthy place to enforce privacy.
Things that cost a day each
A Lambda resource policy needs exactly two wildcards. execute-api:.../*/*
matches an HTTP API’s $default stage; the three-wildcard form silently does
not. The symptom is a 500 from API Gateway with zero Lambda invocations
logged, which is a confusing place to start debugging.
Never call a long-running inference endpoint on its synchronous host from a browser. The sync host holds the connection until generation finishes, which is fine from curl at three seconds and hangs indefinitely in a browser. Use the queue host and poll.
What I would change
There are no automated tests. It was built fast, for an audience of two, and that tradeoff was right at the time — but it is the reason I would not put a third person on it without writing them first.