skip to content

You're the principal engineer advising on architecture for a new B2B SaaS product that will need complex multi-table transactions, strict data-residency guarantees for enterprise customers in the EU, and predictable infrastructure costs at a contracted scale of millions of requests/day. A junior architect proposes building the entire backend on Firebase/Firestore because 'it worked great for our last consumer app.' What's your reasoning for where BaaS composability breaks down here, and what would you recommend instead?

level: principalimportance: should knowfreq 45%

answer

  1. Firestore transactions have document-count/contention limits
  2. residency needs contractual proof, not just region picker
  3. per-op pricing inverts at sustained scale
  4. hybrid: BaaS for peripheral, owned DB for regulated core
  5. match tool to problem shape, don't pattern-match past success

basics

~20 s

BaaS tools are great for simple apps, but this project needs complex multi-step transactions, guaranteed EU-only data storage, and predictable costs at huge scale — things Firestore-style services aren't built to guarantee, so a traditional or hybrid backend fits better.

solid answer

~50 s

Three specific requirements break the BaaS fit here. Firestore's transaction model supports limited multi-document atomicity within constraints (document count, contention), not arbitrary multi-table business transactions the way a relational database with ACID guarantees does. Data residency needs contractual, auditable guarantees about exactly which region data lives and stays in — most BaaS offerings give region selection but not automatically the same compliance tooling (data processing agreements, audit logs, fine-grained residency controls) that enterprise contracts often require, and this needs verifying per-vendor, not assumed. And at millions of requests/day, per-operation BaaS pricing becomes both expensive and unpredictable compared to provisioned/reserved capacity on a traditional database, which enterprise finance teams need for contract budgeting. I'd recommend a relational database (or DynamoDB with careful single-table design) behind a real service layer for the core transactional domain, potentially keeping BaaS for narrow, well-suited slices like consumer-facing notifications, rather than an all-or-nothing choice.

go deeper

for a junior

Should recognize that 'it worked before' isn't sufficient justification and that this project has different requirements, even without detailing exactly which.

for a middle

Should identify at least one of the three concrete mismatches (transactions, residency, cost-at-scale) with a specific technical reason.

for a senior

Should articulate all three mismatches with concrete mechanisms (document-transaction limits, residency compliance specifics, pricing model inversion) and propose a viable alternative like a relational database with a real service layer.

for a principal

Should reason about a hybrid architecture that matches each requirement to the right tool, articulate the general principle of matching tool to problem shape rather than pattern-matching past success, and connect the decision to business/compliance/contractual stakes, not just technical mechanics.

## Why the past success does not transfer The instinct 'it worked for our last app' is exactly the failure mode a principal engineer needs to catch, because BaaS composability is a fit for **a shape of problem** — simple access patterns, single-tenant or loosely related data, elastic consumer traffic — and this project has three requirements that sit outside that shape, each for a distinct technical reason. ## Transactional complexity **First, transactional complexity.** Firestore (and similarly Firebase's peers) supports transactions, but with real constraints: a transaction can touch a limited number of documents, must complete quickly, and retries automatically on contention, which works for 'update a document and a counter together' but breaks down for genuine multi-table, multi-entity business transactions — e.g., 'create an invoice, decrement inventory across three warehouse records, and post a ledger entry, all-or-nothing, potentially touching dozens of rows with complex constraint checks.' A relational database with real **ACID** transactions and foreign-key constraints is built precisely for this: the database engine enforces referential integrity and rolls back the entire operation on any failure, with no document-count ceiling and no need for the application to hand-roll optimistic-retry logic. Trying to force this onto Firestore means either: - restructuring the business transaction into an awkward sequence of smaller, non-atomic writes (opening a window for partial failures/data corruption), or - building a compensating-transaction saga pattern by hand — real distributed-systems engineering effort that a relational database would have given for free. ## Data residency **Second, data residency.** Enterprise EU customers commonly require contractual guarantees — often backed by a Data Processing Agreement and sometimes audited — that data is stored and processed only within specific EU regions, with no replication or backup crossing borders, and with logging/audit trails proving it. Most BaaS platforms let you pick a region for a project, but the guarantee that 'no data or metadata ever leaves that region, including backups, logs, and any managed sub-services the platform uses internally' varies significantly by vendor and by which managed features are enabled, and needs to be verified against the actual vendor contract and compliance documentation, not assumed from 'a region was picked in the console.' A principal engineer's job here is to insist on reading the vendor's specific compliance commitments (data residency addenda, sub-processor lists) against the customer contract's requirements before committing architecture — not to guess. ## Cost predictability at contracted scale **Third, cost predictability at contracted scale.** BaaS pricing is per-operation (per document read/write, per auth verification, per function invocation), which is attractive at low, spiky consumer traffic because it scales to zero. At a contracted millions-of-requests/day floor, that same model inverts: the company now has a known, large, sustained load, which is exactly the situation where reserved/provisioned capacity (a sized relational database instance, or DynamoDB provisioned capacity with savings plans) is both cheaper and, critically, budgetable — finance teams pricing a multi-year enterprise contract need to forecast infrastructure cost as a predictable line item, not a usage-metered variable that could spike with a client's unexpected traffic pattern or a batch job gone wrong. ## The recommendation, sliced by requirement Given all three, my recommendation is not 'abandon managed services entirely' but to be precise about which slice of the system each requirement applies to. - The **core transactional domain** — the invoicing/inventory/ledger logic with strict consistency and audit needs — belongs on a traditional relational database (e.g., Postgres) behind a real service layer that owns transaction boundaries explicitly, deployed in infrastructure where region and data flow are fully under contractual control, sized with provisioned/reserved capacity for cost predictability. - Meanwhile, genuinely **BaaS-shaped slices of the same product** — say, sending transactional emails, or handling non-sensitive user-preference storage that doesn't touch the residency-controlled domain — can still reasonably use managed services, because the composability and velocity benefits are real where the constraints don't bite. This hybrid approach is common in real enterprise architectures: the regulated, transactional core sits on owned or tightly-controlled infrastructure, while peripheral, low-stakes functionality is composed from managed services. ## The broader principle The broader principle a principal engineer should be applying, and teaching the junior architect, is that BaaS composability is a tool matched to a problem shape — elastic traffic, simple per-entity access patterns, no hard cross-border data constraints, correctness needs that tolerate eventual consistency — and reusing a past success uncritically means checking whether this problem still has that shape, rather than pattern-matching on 'it worked before.' The right question isn't 'can Firestore technically do this,' since with enough workaround engineering it often technically can, but 'does forcing this problem into Firestore's model cost more in workaround complexity, compliance risk, and unpredictable spend than building the transactional core properly would.'

  • Why can't the multi-table invoicing/inventory/ledger transaction in this scenario just be split into several smaller Firestore transactions run in sequence?
    Splitting it removes atomicity — if the third step fails after the first two succeeded, the system is left in a partially-updated, inconsistent state (inventory decremented but no ledger entry, for instance), and someone has to detect and repair that manually or build a compensating-transaction saga. A relational database's multi-table ACID transaction avoids this by making the whole operation succeed or fail as one unit at the database engine level.
  • The junior architect points out Firestore lets you pick a specific region. Why isn't that enough to satisfy the EU data-residency requirement on its own?
    Region selection typically controls where the primary data lives, but enterprise residency requirements often also cover backups, logs, and any sub-processors or managed features the platform uses internally, plus require contractual/audit evidence, not just a configuration setting. Those specifics vary by vendor and must be checked against the vendor's actual compliance documentation and the customer's contract, not assumed from the console UI.
  • Why does per-operation BaaS pricing become a liability specifically at millions of requests/day, when it was an advantage for the previous consumer app?
    At low, spiky consumer traffic, per-operation pricing scales to near-zero cost during quiet periods, which is exactly the advantage. At a sustained, contracted volume, that same variable-cost model removes the predictability an enterprise finance team needs to budget a multi-year contract, and reserved/provisioned capacity typically becomes cheaper per unit at that volume anyway — the trade-off that favored BaaS at low scale reverses at high, steady scale.

It's like choosing a rental moving van for a cross-town apartment move versus a dedicated freight contract for shipping a factory's output every day: the van is cheap and flexible for occasional, small, unpredictable loads, but once you have a guaranteed, massive, recurring volume with strict chain-of-custody requirements, a dedicated contract with fixed capacity and accountability is what actually fits.

saying these in an interview costs you the question

  • Recommends Firestore/BaaS for the regulated transactional core without checking vendor-specific compliance guarantees
  • Assumes picking a database region alone satisfies enterprise data-residency contract requirements
  • Doesn't recognize that BaaS transaction primitives have real scope limits (document count, contention) versus full ACID
  • Treats the decision as all-or-nothing (either BaaS everywhere or none) instead of considering a hybrid split
  • Ignores that pricing models which are cheap at low scale can become expensive/unpredictable at sustained high scale

context