Engineering
Choosing a Backend Stack for a Small Team
Backend architecture decisions get made in a vacuum more often than any other early technical choice — an engineer picks what they know best, or what's trending, without weighing it against the team's actual size and the product's actual data shape. For a small team, the right answer is usually narrower than the options make it look.
Firebase — Auth, Firestore, Functions, Storage
Firebase remains the fastest path from zero to a working authenticated app with real-time data sync, tight first-party SDKs on iOS and Android, and a genuinely generous free tier for early-stage traffic. Its tradeoffs are real: Firestore's NoSQL document model makes complex relational queries (joins across collections, in particular) awkward compared to SQL, and cost curves can climb quickly once you're at meaningful scale with heavy read/write patterns. Security rules take real care to get right — an over-permissive rule set is a common, quietly serious mistake.
Supabase
Supabase pairs a real Postgres database with Auth, Storage, and Edge Functions on top, open-source and self-hostable if you ever need to leave the managed service. When your data model is genuinely relational — orders that reference customers that reference products, with real joins and constraints — Postgres and row-level security policies are a more natural fit than a document database, and you keep the option to write actual SQL for reporting and analytics later.
Custom Node/Express or FastAPI with managed Postgres
Rolling your own backend gives full control and zero platform lock-in, at the cost of owning authentication, infrastructure, scaling, and operations yourself. This is the right call when your requirements are genuinely unusual — an existing system to integrate deeply with, compliance requirements a managed platform doesn't cover well, or a team that already has backend engineers and infrastructure experience sitting idle. It's rarely the right call purely because it feels more "real" than a managed backend.
Serverless vs. always-on
Cloud Functions, Cloud Run, and Lambda-style serverless compute scale to zero and back up automatically, which is ideal for early-stage, spiky, or low-traffic workloads — you don't pay for idle capacity, at the cost of occasional cold-start latency. A small, always-on server is more predictable in latency but you're paying for capacity around the clock whether it's used or not. For most early products, serverless wins on cost; for latency-sensitive real-time features, an always-on process is often worth the tradeoff.
What actually matters for a one-to-three person team
- Time to first real user beats architectural purity — a working product with a managed backend today outperforms a perfectly architected one that ships two months later
- Pick the stack your team already knows well over the one that's theoretically more powerful
- Avoid microservices at MVP stage — a single well-organized backend is easier for a small team to reason about and deploy
- Use managed authentication instead of rolling your own — session handling, password resets, and social login all have sharp edges that aren't worth relearning
- Plan for a migration path, not a rewrite — pick a stack you can grow inside of for a while, not one you'll have to replace at the first sign of real traffic
Observability from day one, not after the first incident
Small teams routinely skip logging, error tracking, and basic uptime monitoring until something breaks in production and there's no record of what happened. This is one of the cheapest investments available — a managed backend's built-in logging plus a lightweight error-tracking tool costs little in setup time and pays for itself the first time a user reports a problem you'd otherwise have no way to diagnose. Treat it as part of the initial build, not a follow-up task for "later."
Authentication complexity grows faster than people expect
A single-tenant app with email/password login is simple regardless of backend choice. The complexity shows up later — adding social login providers, supporting multiple organizations or teams per account, role-based permissions, or single sign-on for an enterprise customer. Managed auth providers (Firebase Auth, Supabase Auth, Clerk) handle most of this progression without a rewrite; a hand-rolled auth system built for the simple case often needs real surgery once a customer asks for SSO or team accounts, which is one more reason to default to managed auth even on a stack you otherwise built yourself.
We run Firebase/GCP for most client products where the data is naturally document-shaped and the team wants managed infrastructure, and Postgres-backed services when the data model is genuinely relational or the client already has backend engineering in-house. Neither is the "correct" default — the product's data shape and the team's existing skills should decide it.
More from the journal
Planning
Custom App Development: Realistic Cost and Timeline Expectations
"How much will this cost" and "how long will this take" are the first two questions every founder asks — and the honest answer is always a range driven by a specific set of variables, not a fixed number.
Growth
Post-Launch: Setting Up Analytics and Iterating on Real Usage
Launch is when the guessing should stop. Here's the minimum analytics setup that turns real usage into an actual product roadmap.
Engineering
iOS App Permissions Explained: What to Ask For, and When
Every permission prompt is a small negotiation with the user. Understanding what each one actually unlocks — and what happens after a decline — changes how you should ask.