01Firestore over a relational database
- Why
- The managed Postgres it replaced paused on inactivity, and a paused database took the whole API down with it — including endpoints that never touched a database. Firestore's free tier does not pause.
- Cost
- No SQL, no joins, no versioned migrations. Document ids stopped being integers, so the public contract changed and the frontend changed with it.
04Firestore reads stay inside the C# API
- Why
- The front end could read Firestore directly and skip a network hop entirely. Keeping the read here preserves one place that owns data access, and keeps the C# service a real piece of work rather than a thin proxy around someone else's SDK.
- Cost
- The API sits on the critical path of every page load, so its cold start is the page's cold start. Cutting it out would have made the site faster and the portfolio smaller.
05The service account lives in an environment variable
- Why
- Render offers no convenient disk for a credential file, so the whole service account JSON is passed as a single environment variable, falling back to Application Default Credentials when it is empty.
- Cost
- A large secret in an env var that must never reach the repository. The .NET web SDK also treats every .json in the project as content and copies it into the published image, so the container needed its own .dockerignore to stop a local build from baking the key in.