Database Selection and Trade-offs Questions
Choosing the right database and data platform for a workload: relational versus NoSQL versus specialized stores, managed versus self-hosted, and matching technology to consistency, scale, cost, and query or access-pattern needs. Covers OLTP versus OLAP and transactional-versus-analytical workload splits, polyglot persistence across multiple data stores, structuring an ambiguous selection prompt, naming trade-offs, and defending a recommendation to stakeholders.
You're the TPM owning a product that stores both relational customer data and high-volume event logs. Compare relational databases and NoSQL alternatives at a product decision level: data model flexibility, consistency guarantees, query capabilities, operational cost, backup/recovery, and how each choice affects API semantics and SLAs for developers.
Sample Answer
Direct answer
Treat this as a product decision with three downstream effects your engineers will hand back to you as constraints: how fast you can ship new kinds of data, what promises you can make customers about correctness, and what your application programming interface (API, the contract client applications use to talk to your service) can promise about response time and failure behavior. Relational databases (SQL, structured query language databases such as PostgreSQL or MySQL) default to strict, all-or-nothing correctness and rich cross-entity querying, at the cost of more planning before adding new kinds of data. NoSQL stores, a broad label for non-relational databases such as DynamoDB or MongoDB, default to flexible schemas and horizontal scale, at the cost of some correctness guarantees you must design around explicitly instead of getting for free.
Structured elaboration
Data model flexibility. Relational is like a spreadsheet with fixed columns everyone agreed on ahead of time; adding a column is usually easy, but restructuring existing data is a real engineering project your team has to schedule. A document-style NoSQL store lets every record carry its own shape; faster to evolve, but it pushes the responsibility for "does this data look right" onto the application instead of the database enforcing it.
Consistency guarantees. Relational databases default to atomicity, consistency, isolation, and durability (ACID), the guarantee that a multi-step update either fully happens or fully does not. If your product promises "your payment and your order status update together, always," that promise is cheap to keep on a relational database and requires deliberate extra engineering on many NoSQL stores.
Query capability. Relational lets analysts and engineers ask new questions of the data without redesigning anything, a join across tables that never anticipated that specific question. Most NoSQL stores need the access pattern known up front, designed into the storage keys; a new kind of question later can mean a new table or index and sometimes a data migration.
Operational cost. Relational databases, self-hosted or managed, typically bill for a provisioned server regardless of how busy it is. Many NoSQL services bill per request, cheaper at low or spiky volume, and potentially more expensive than a flat instance price at very high sustained volume. This is worth an actual cost model before committing, not a rule of thumb either way.
Backup and recovery. Both families support automated backups and point-in-time recovery on managed offerings. The practical difference customers feel is recovery time, how long until service is back, and recovery point, how much recent data, if any, is lost, which is mostly a configuration choice, how many replicas, synchronous or asynchronous, rather than an inherent property of relational versus NoSQL. Relational's transactional model does make it easier to reason precisely about exactly what state was recovered to.
How this ripples into API semantics and developer SLAs. If the data layer is eventually consistent, the API cannot honestly promise "you'll see your own change immediately" to every caller without extra engineering built specifically for that. That is a product-facing promise your team commits to in a service-level agreement, not just an implementation detail, and it dictates what your frontend and mobile engineers must build to cover the gap.
Worked example
A concrete decision memo: adding a customer loyalty-points ledger. Loyalty points must never be double-awarded or lost, relational, ACID, non-negotiable. Marketing wants to add new promotional metadata fields weekly without an engineering migration each time, so that flexible part goes into a JSONB or document-shaped column, or a separate flexible-schema store, never the ledger table itself. Splitting responsibility this way costs little and buys both properties, rather than forcing one technology to satisfy both needs at once.
Trade-offs and pitfalls
A pitfall specific to this audience is approving "just use NoSQL, it's more scalable" as a blanket policy. Scalability is a property of throughput and data volume, not of the relational-versus-NoSQL label; a well-run relational database handles enormous scale for the right access pattern, and a badly designed NoSQL schema can be just as bottlenecked.
A second pitfall is underestimating that a consistency trade-off made at the database layer becomes a product and support problem later, customers reporting "my order, points, or message disappeared and came back", if engineering does not explicitly design for it up front.
What changes the recommendation: a product with no cross-entity correctness requirements and extremely spiky, unpredictable traffic, for example a viral content app, leans NoSQL by default. A product whose core value is trustworthy, auditable record-keeping, billing, compliance, loyalty points, leans relational for that specific core ledger, even if other parts of the same product use NoSQL for different needs.
You must choose between a managed cloud OLAP service (e.g., BigQuery) and self-managed columnar cluster (e.g., Presto+Parquet on Kubernetes) for an analytics team. Compare them across performance predictability, TCO, administrative overhead, query concurrency, and vendor lock-in. For a team with 20 analysts and occasional heavy ad-hoc queries, which would you recommend and why?
Sample Answer
Direct answer
For a team of 20 analysts running occasional heavy ad-hoc queries, recommend the managed cloud OLAP (online analytical processing: query patterns dominated by large scans and aggregations, as opposed to OLTP, online transaction processing, which is dominated by many small transactional writes) service, BigQuery, over a self-managed Presto+Parquet cluster on Kubernetes. The deciding factor is not raw compute cost, where the two are close, but that a self-managed cluster is provisioned capacity billed whether it's busy or idle, and it needs a platform team to keep it healthy; at 20 analysts' actual query volume, that fixed cost overwhelms any per-query savings self-hosting offers.
Comparing the two on the five stated axes
| Axis | BigQuery (managed) | Presto+Parquet on Kubernetes (self-managed) |
|---|---|---|
| Performance predictability | Google auto-scales query execution; a single expensive ad-hoc query doesn't need capacity planning from your team, but concurrent heavy queries share a per-project fair-scheduling pool that can slow each other down unpredictably under load | Fully predictable only if you've provisioned for peak concurrency; if 20 analysts all fire heavy queries at once and you provisioned for average load, everyone queues |
| TCO (total cost of ownership) | Pay per TB scanned plus storage; no infrastructure or platform-team cost | Compute and storage costs plus a platform team's fully loaded salary to operate Kubernetes, Presto, and the Parquet layout; see the worked example below for how much that staffing line matters |
| Administrative overhead | Near zero: no cluster to patch, scale, or keep alive | Real, ongoing: Presto version upgrades, Kubernetes node management, Parquet file compaction (periodically rewriting many small files into fewer, larger ones so scans stay fast) and small-file cleanup, query engine tuning |
| Query concurrency | Google manages resource allocation across concurrent queries within your project's slot allotment | You own the scheduler configuration and capacity headroom; under-provisioning shows up as analysts waiting on each other's queries |
| Vendor lock-in | Real: BigQuery's SQL dialect and storage format are Google-specific, and moving off it later means rewriting queries and re-exporting data | Minimal: Parquet is an open, portable file format and Presto/Trino run on any infrastructure, so this stack is the more portable choice if lock-in is the team's top concern |
Cloud pricing components to model, explicitly
A cost comparison that skips any of these components understates one side or the other:
- Compute: BigQuery's per-TB-scanned on-demand rate, or a flat-rate/editions commitment; self-managed compute-hours for the Kubernetes node pool.
- Storage: BigQuery's active logical storage rate; object storage (S3/GCS-class: services like Amazon S3 or Google Cloud Storage that store flat, key-addressed files rather than a traditional filesystem) for the Parquet files in the self-managed case.
- Network egress: cost of moving data out of the cloud region or between the storage layer and compute nodes, often ignored until a cross-region setup makes it material.
- Committed-use / reserved discounts: BigQuery editions/flat-rate slots, or reserved-instance pricing for the self-managed nodes; both can shift the comparison significantly at steady, predictable load.
- Support tier cost: enterprise support contracts, if the team needs guaranteed response times, are a real line item on either side that's easy to forget in a first-pass estimate.
Worked example
Verified current BigQuery rates (cloud.google.com/bigquery/pricing, checked 2026-09-24): on-demand analysis at $6.25 per TiB scanned (US multi-region), with the first 1 TiB/month free, and active logical storage at $0.02 per GiB-month. Model 20 analysts each running 15 queries/day, 22 working days/month, averaging 50 GiB scanned per query, against a 20 TiB resident dataset.
analysts, queries_per_day, days = 20, 15, 22
scan_per_query_GiB, dataset_GiB = 50, 20_000
queries_per_month = analysts * queries_per_day * days
scanned_TiB = queries_per_month * scan_per_query_GiB / 1024
print(f"queries/month: {queries_per_month:,}, scanned: {scanned_TiB:.1f} TiB")
bq_compute = max(0, scanned_TiB - 1) * 6.25 # VERIFIED rate, first 1 TiB free
bq_storage = dataset_GiB * 0.02 # VERIFIED rate
print(f"BigQuery: ${bq_compute + bq_storage:,.2f}/mo (compute ${bq_compute:,.2f} + storage ${bq_storage:,.2f})")
# Self-managed: ASSUMPTION rates, pinned explicitly (no live quote for a specific node type)
nodes, vcpu_per_node, compute_rate = 10, 16, 0.045
storage_rate, fte, salary = 0.023, 1.5, 190_000
sm_compute = nodes * vcpu_per_node * compute_rate * 730
sm_storage = dataset_GiB * storage_rate
sm_staffing = fte * salary / 12
sm_total = sm_compute + sm_storage + sm_staffing
print(f"Self-managed: ${sm_total:,.2f}/mo (compute ${sm_compute:,.2f} + storage ${sm_storage:,.2f} + staffing ${sm_staffing:,.2f})")
queries/month: 6,600, scanned: 322.3 TiB
BigQuery: $2,407.91/mo (compute $2,007.91 + storage $400.00)
Self-managed: $29,466.00/mo (compute $5,256.00 + storage $460.00 + staffing $23,750.00)
At this team's actual query volume, BigQuery costs about 12x less than the self-managed cluster, almost entirely because the self-managed side pays for 1.5 platform engineers (an assumed, but realistic, staffing level to keep Presto and Kubernetes healthy) whether or not the cluster is busy. The break-even point, where BigQuery's scanned-data cost alone equals the self-managed cluster's fixed compute-plus-storage-plus-staffing cost, works out to roughly 4,700 TiB scanned per month in this model: about 15x this team's actual usage. Self-hosting would only become competitive if the team's query volume grew far beyond what 20 analysts running occasional heavy queries would plausibly generate, or if the platform team's time were already a sunk cost shared across other self-hosted systems.
Trade-offs and pitfalls
- The recommendation flips on scale, not on principle. Once sustained scanned-data volume is high enough (roughly 15x this team's usage, per the break-even above), the self-managed cluster's fixed cost starts to look cheap relative to BigQuery's linear per-scan billing.
- Vendor lock-in is real and worth naming, even when recommending BigQuery. If portability is a hard organizational requirement (regulatory, multi-cloud strategy), that can outweigh the cost argument; that's a legitimate reason to choose the more expensive, more portable option deliberately.
- BigQuery's on-demand billing rewards query discipline. An unindexed
SELECT *over a huge table is expensive precisely because you pay per byte scanned; partitioning and clustering the underlying tables materially changes the cost side of this comparison and should be table stakes before concluding BigQuery is "too expensive." - A self-managed estimate that omits Parquet file compaction and small-file cleanup will understate the real operational burden. Small-file proliferation from frequent writes is one of the most common sources of unplanned Presto-on-Parquet maintenance work.
As an SRE, explain the operational differences between relational databases (e.g., PostgreSQL) and NoSQL stores (e.g., Cassandra, DynamoDB). Focus on availability, consistency, scaling patterns, backup/recovery, schema evolution, and common operational pitfalls. Give concrete examples of workloads where you'd choose one over the other and why, and describe the SRE operational changes required for each choice.
Sample Answer
Direct answer
Running Postgres and running Cassandra or DynamoDB in production are operationally different jobs, not just different query languages: a relational engine concentrates availability risk on a single primary that must be failed over correctly, while a leaderless or managed NoSQL store spreads both the write path and the failure domain across many replicas, trading "one thing to get right" for "many things that must stay in agreement."
Structured elaboration
| Dimension | Relational (Postgres) | NoSQL (Cassandra / DynamoDB) |
|---|---|---|
| Availability model | Single-writer primary plus replicas; failover needs orchestration (for example Patroni plus a consensus store) to promote a replica without a split-brain | Multi-writer or leaderless quorum (Cassandra) or fully managed multi-active partitions (DynamoDB); no single node's failure blocks writes |
| Consistency model | Strong by default on the primary | Tunable per query (Cassandra) or eventual-by-default with optional strong reads (DynamoDB) |
| Scaling pattern | Vertical plus read replicas; horizontal write scaling needs manual sharding | Horizontal partition-key sharding built in from the start |
| Backup / recovery | Point-in-time recovery via write-ahead log (WAL) replay or continuous archiving: a well-understood, single-timeline process | Per-node snapshots (Cassandra) that must be restored consistently across the whole ring, more moving parts to get right; DynamoDB backups are fully managed but restore into a new table, changing the operational runbook |
| Schema evolution | ALTER TABLE is a coordinated, sometimes-blocking data-definition operation that needs careful sequencing on a large table | Adding a new attribute to new writes needs no blocking migration; the trade is that the application, not the engine, owns enforcing the new field's presence and shape |
| Common pitfalls | Connection exhaustion under load without pooling; a bad migration locking a hot table | Hot partitions from a poorly chosen partition key; underestimating repair/anti-entropy scheduling (Cassandra), the background jobs that compare replicas against each other and resync any that have drifted out of agreement, or throttling under provisioned-capacity limits (DynamoDB) |
Worked example: an analytics platform ingesting structured application logs alongside semi-structured event payloads (variable JSON fields per event type), at high, bursty write volume, feeding downstream dashboards.
- Postgres: schema evolution becomes a real risk here, since a blocking
ALTER TABLEon a huge, actively-written logs table needs careful online-migration tooling to avoid an outage, and a single-primary availability model is exposed to bursty write spikes overwhelming one node. - Cassandra or DynamoDB: absorbs schema evolution and horizontal write scale comfortably, but the team now owns quorum and repair health (self-managed Cassandra) or partition hot-key and capacity-unit monitoring (DynamoDB), plus a multi-node backup and restore runbook instead of a single-timeline one.
- A columnar analytical engine (BigQuery or ClickHouse), purpose-built for exactly this log/event shape: schema evolution is cheap (new nullable columns), ingestion is typically a batch or streaming insert application programming interface (API) rather than a transactional write path, and BigQuery in particular removes cluster-capacity ownership entirely (a fully managed, serverless engine), while ClickHouse trades that operational simplicity away for lower cost and more control, at the price of the team owning background merge and compaction health themselves (compaction: periodically combining and rewriting many small stored files into fewer, larger ones to keep storage and query performance from degrading).
The operational changes each choice actually requires of the team:
- Postgres: own failover orchestration and rehearsed point-in-time recovery drills, connection pooling to avoid exhaustion, and careful sequencing of schema migrations.
- Cassandra / DynamoDB: own repair and anti-entropy scheduling (self-managed Cassandra) or capacity and throttling monitoring (DynamoDB), design explicitly around avoiding partition hot-keys, and rehearse multi-region backup and restore.
- Columnar OLAP (BigQuery / ClickHouse): own ingestion pipeline health and backpressure, and for self-managed ClickHouse, background merge and disk-space monitoring; for managed BigQuery, own query-cost and slot monitoring instead of cluster health.
Trade-offs & pitfalls
The most common operationally-visible pitfall is assuming "the NoSQL store scales itself" only covers scaling THROUGHPUT, not scaling the TEAM'S operational knowledge; a Cassandra ring with an inconsistent replica count after a bad node decommission is a genuinely different, often less familiar, failure class than "the Postgres primary died," and backup and recovery drills need to be rehearsed per system rather than assumed to transfer from one engine's runbook to another's.
Your organization is concerned about vendor lock-in after adopting a managed cloud analytics service. Propose concrete strategies to minimize lock-in risk while benefiting from managed services: data export portability, use of open file formats, decoupling compute from storage, and operational processes to make migration feasible.
Sample Answer
Direct answer
Land data in an open, columnar file format in storage you control, not the vendor's proprietary internal representation; keep the storage layer decoupled from the query engine so a different engine could read the same files; automate a recurring, tested export rather than relying on a one-time "we could leave if we needed to" claim; and keep transformation logic in vendor-neutral tooling instead of the vendor's proprietary pipeline UI.
Structured elaboration
Open file formats
Land raw and curated data as Parquet (a columnar, compressed, self-describing file format nearly every analytics engine, including a future replacement, can read directly), optionally managed by an open table format like Apache Iceberg or Delta Lake (a metadata layer that tracks a table's schema, partitions, and file versions on top of the underlying Parquet files, so more than one engine can safely read and write the same table), rather than letting data live only inside a proprietary warehouse's internal storage representation.
Decoupling compute from storage
Keep those files in your own object storage bucket as the actual source of truth, and treat the managed analytics service as a compute engine that reads that storage, not a system that owns and internally encodes your data. If the files are portable, swapping which engine queries them becomes a compute-layer decision, not a full data migration.
Data export and portability discipline
Don't treat exportability as a one-time claim from the vendor evaluation document. Put a scheduled job in place that actually exports a representative slice of data on a real cadence and verifies it lands correctly in the open format, so "we could leave" is a tested, working capability rather than an assumption that turns out to be wrong exactly when you need it.
Operational processes
Keep the SQL that turns raw tables into curated ones in a vendor-neutral tool that compiles to standard SQL, rather than the vendor's low-code pipeline UI, and keep infrastructure-as-code definitions of the pipeline outside the vendor's console so its shape is documented and reproducible against a different engine. Track and periodically re-estimate the actual dollar and engineering-time cost of a hypothetical migration, an exit-cost line item revisited yearly, which turns lock-in from a vague fear into a number the organization can decide to accept or address.
Worked example
Raw ingested events land as Parquet files partitioned by date in an object storage bucket the organization owns. The managed cloud data warehouse is pointed at that bucket as external or staged tables (the warehouse queries the files where they already sit in your own storage, instead of copying them into its own internal storage first) rather than being the only place the data lives. Transformations are written as models in a vendor-neutral tool that compiles to portable SQL and are version-controlled outside the vendor's console. Once a quarter, an automated job spins up an alternate open-source query engine against the same Parquet files and runs a handful of the production queries, comparing results, which is the tested exit capability, not a claim on paper.
Trade-offs & pitfalls
None of this is free. Landing data in your own storage and keeping the pipeline vendor-neutral gives up some of the managed service's most convenient proprietary features, auto-optimized proprietary storage layouts, one-click pipeline UIs, and adds real engineering effort to build and maintain the portability tests. A team should invest in the full version of this only if a migration is a genuinely plausible future, not apply it reflexively to every vendor relationship regardless of actual switching risk. The most common pitfall is doing the open-format part, which is cheap and mostly automatic with modern warehouses, and skipping the periodic exit-test job, which requires real ongoing effort, leaving the organization with a false sense of portability that was never actually verified.
You must choose a storage strategy for an ML platform, but the infra team (cost-focused) and the data science team (speed-focused) disagree. Describe a structured decision process: how you would evaluate the options quantitatively, run a pilot to validate assumptions, align the two stakeholder groups, and make a final call that minimizes disruption. Include how you would communicate the decision and what your rollback plan would be.
Sample Answer
Direct answer
I would not try to resolve "infra wants cheap, data science wants fast" as a debate about whose priority wins. I would convert it into a shared decision process: get both teams to agree, in writing, on what "cost" and "speed" mean as actual numbers for this workload before evaluating a single technology, replace the argument with a short, time-boxed pilot measured against those agreed numbers, make the call transparently against that pre-agreed criteria, and treat communication and rollback as part of the decision itself, not an afterthought once a winner is picked.
The decision process, step by step
1. Frame the trade-off quantitatively, before anyone proposes an option. Get both teams in the same room and turn each side's position into a number: infra states a hard monthly budget ceiling, data science states a target such as p95 (95th percentile, meaning 95 percent of requests are faster than this) query latency. Written down as joint constraints on the same decision, the two positions stop being a values argument ("cost matters more" versus "speed matters more") and become a trade-off surface you can actually evaluate options against. If, once written down, nothing on the market satisfies both constraints, that itself is the finding, and it needs to be escalated honestly rather than resolved by whoever argues loudest.
2. Shortlist and score on paper first. Narrow the field to two to four realistic candidates, and build a lightweight cost model (compute, storage, and operational overhead) and a rough latency or throughput estimate from public benchmarks and vendor documentation for each, before spending any pilot time. Discard anything that clearly fails a hard constraint from step 1.
3. Run a pilot to make the trade-off empirical, not rhetorical. Load a representative (not full) slice of production data and the workload's actual hardest queries into the top two remaining candidates, and measure the same metrics for both: dollars per unit of workload, p95/p99 (95th and 99th percentile) latency, and a proxy for operational burden such as the number of manual interventions or alerts fired during the pilot window. Time-box it, roughly one to two weeks, so it cannot turn into an open-ended bake-off where each side just waits for numbers that favor it.
4. Align the two stakeholder groups on the results. Bring the pilot's numbers back to both teams together, not separately, and score them against the criteria they both signed off on in step 1, not criteria introduced after seeing who is losing (a common failure mode is quietly re-weighting the scorecard once the result is known). Where the winning option under-serves one team's original number, name that gap explicitly and get an actual acknowledgment, not silence, that the trade-off is acceptable, or escalate it.
5. Make the final call and minimize disruption. Decide, then document a short decision record (what was chosen, the alternatives considered, and the specific, measurable condition that would trigger revisiting it, for example "if write volume exceeds twice the pilot's projection" or "if p95 breaches the agreed target for N consecutive days"). Sequence the migration to touch the smallest reasonable blast radius first, a low-traffic table or service before the primary one, because that sequencing choice, not just which technology won, is what actually minimizes disruption.
6. Communicate the decision. Announce the decision with the reasoning, not just the outcome: the agreed criteria, the pilot's numbers, and where each team's original ask landed, delivered to both teams and any downstream consumers of the data. Set an explicit checkpoint, for example 90 days after cutover, to revisit with real production numbers instead of pilot numbers.
7. Define the rollback plan before cutover, not after something breaks. Concretely define what rollback means for this specific choice: run a dual-write or shadow-read period so the old store stays live and in sync for a fixed window, write a scripted cutback runbook, and set an explicit, numeric rollback trigger agreed in advance, for example "if the error rate exceeds X percent or latency regresses more than Y percent within the first week, we revert." A rollback decided under production pressure should be a checklist someone already agreed to, not a negotiation happening in an incident channel.
Worked example
Two options came out of the shortlist: a cheaper, slower one that infra prefers, and a pricier, faster one that data science prefers. Both teams agreed in step 1 that cost and speed matter equally (weight 0.4 each) and operational burden matters somewhat less (weight 0.2).
options = {
"Option A (infra-favored: cheaper, slower)": {
"compute_usd_per_month": 1_200,
"storage_usd_per_gb_month": 0.023,
"data_gb": 20_000,
"p95_query_ms": 850,
},
"Option B (DS-favored: pricier, faster)": {
"compute_usd_per_month": 4_800,
"storage_usd_per_gb_month": 0.10,
"data_gb": 20_000,
"p95_query_ms": 120,
},
}
weights = {"cost": 0.4, "speed": 0.4, "ops_burden": 0.2} # agreed by both teams in step 1
ops_burden_score = {"Option A (infra-favored: cheaper, slower)": 0.8, # 0-1, 1 = lowest burden
"Option B (DS-favored: pricier, faster)": 0.5}
results = {}
for name, o in options.items():
monthly_cost = o["compute_usd_per_month"] + o["storage_usd_per_gb_month"] * o["data_gb"]
results[name] = {"monthly_cost_usd": monthly_cost, "p95_query_ms": o["p95_query_ms"]}
print(f"{name}: ${monthly_cost:,.0f}/month, p95 = {o['p95_query_ms']} ms")
costs = [r["monthly_cost_usd"] for r in results.values()]
lats = [r["p95_query_ms"] for r in results.values()]
cmin, cmax = min(costs), max(costs)
lmin, lmax = min(lats), max(lats)
print()
for name, r in results.items():
cost_score = 1 - (r["monthly_cost_usd"] - cmin) / (cmax - cmin) if cmax != cmin else 1.0
speed_score = 1 - (r["p95_query_ms"] - lmin) / (lmax - lmin) if lmax != lmin else 1.0
burden = ops_burden_score[name]
total = weights["cost"] * cost_score + weights["speed"] * speed_score + weights["ops_burden"] * burden
print(f"{name}: cost_score={cost_score:.2f} speed_score={speed_score:.2f} "
f"ops_score={burden:.2f} -> weighted_total={total:.3f}")
Output:
Option A (infra-favored: cheaper, slower): $1,660/month, p95 = 850 ms
Option B (DS-favored: pricier, faster): $6,800/month, p95 = 120 ms
Option A (infra-favored: cheaper, slower): cost_score=1.00 speed_score=0.00 ops_score=0.80 -> weighted_total=0.560
Option B (DS-favored: pricier, faster): cost_score=0.00 speed_score=1.00 ops_score=0.50 -> weighted_total=0.500
score(o)=wcost⋅scost(o)+wspeed⋅sspeed(o)+wops⋅sops(o)
Option A wins, 0.560 to 0.500, a margin of 0.06 on a 0-1 scale. That narrowness is itself a piece of information worth communicating: this was not a landslide, so the write-up to both teams should say the call was close, the data science team's speed concern was real and only barely outweighed, and the rollback plan and 90-day review checkpoint matter more here than they would for a lopsided result.
Trade-offs and pitfalls
- Common wrong turn: presenting a comparison deck and asking each team to vote. That proceduralizes a popularity contest instead of resolving anything, and it tends to produce a worse decision than either team's original instinct, because a deck omits which parts of each option would need a workaround after launch.
- Common wrong turn: running the pilot without agreeing on criteria first. Without that, both sides re-litigate afterward by pointing to whichever sub-metric favors them, and the pilot bought nothing.
- Pitfall: choosing a "split the difference" hybrid to avoid conflict when the pilot data clearly favors one option. A negotiated compromise that ignores the numbers you just measured throws away the value of running the pilot at all.
- Pitfall: skipping the rollback plan because everyone feels confident about the call. That confidence is exactly when it is easiest to skip, and exactly when skipping it is most expensive if the decision turns out wrong.
- Escalation path: if the pilot genuinely ties on the agreed criteria, escalate with that same evidence to a joint decision-owner, an architecture review or the teams' shared manager, rather than let the disagreement continue indefinitely. A tie is itself a valid, informative pilot outcome, not a failure of the process.
Unlock Full Question Bank
Get access to all 35 Database Selection and Trade-offs interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.