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 must advise whether to adopt an open-source database technology or purchase an enterprise DB offering for a regulated financial client. Describe the evaluation process: TCO over 3–5 years, supportability, security patching, licensing/legal risk, staff skills, SLAs, and your recommendation with mitigations for the decision's principal risks.
Sample Answer
Direct answer
For a regulated financial client, recommend an open-source database engine paired with a paid commercial support contract, rather than either a purely community-supported open-source deployment or a fully proprietary enterprise engine. A regulated environment needs a contractually-backed support SLA and a documented patch-liability chain, and that is purchasable for a mature open-source engine without taking on a proprietary engine's licensing cost and deeper lock-in.
Structured elaboration
| Dimension | Proprietary enterprise database | Open source, community only | Open source with a commercial support contract |
|---|---|---|---|
| TCO (total cost of ownership) over 3 to 5 years | Ongoing per-core or per-instance license fees on top of infrastructure, a real and growing cost as the deployment scales | Zero license cost, but the cost moves into in-house expertise the organization must build and retain | Usually cheaper than proprietary licensing at moderate scale, but not free: a support subscription fee replaces the license fee |
| Supportability | A single vendor to escalate to, with a contractual response-time commitment | Excellent public knowledge base and community response, but no one is contractually obligated to answer, and no guaranteed response time | Restores a contractual SLA while the underlying software stays open |
| Security patching | Vendor publishes advisories and a patch SLA | Fixes land in the public repository immediately, often faster than a proprietary vendor's release cycle, but no one is obligated to notify you or help you apply them under audit pressure | Vendor typically publishes advisories and commits to a patch or mitigation SLA on top of the public fix |
| Licensing and legal risk | Audit clauses let the vendor examine your deployment for license compliance, with real deep vendor lock-in through proprietary dialects and tooling | Risk shifts to correctly tracking which license variant a given project and its extensions actually use, since some open-source projects have moved to source-available licenses with usage restrictions in recent years | Same licensing-tracking risk as pure community, plus a support contract to review for its own terms |
| Staff skills | Scarcer, more expensive talent for a niche proprietary engine | Large, portable talent pool for a mainstream open-source engine like PostgreSQL or MySQL | Same large talent pool, plus a vendor relationship that doesn't require every engineer to be an expert |
| SLAs | Contractual uptime and response-time commitments with financial remedies | None. A service-level agreement (SLA: a contractual commitment to a response time or uptime target, usually with a financial remedy if missed) does not exist for community-only support, which a bank's own auditors will typically flag as a gap | Contractual, purchased separately from the license |
Worked example
A hypothetical regulated client running a core-banking-adjacent reporting system: recommend PostgreSQL, encrypted at rest and in transit, with a commercial support subscription whose SLA terms (severity-1 response time, patch delivery commitment) are documented as part of the audit evidence package. Principal risks and mitigations: (1) no single vendor to hold accountable in a fully self-integrated open-source stack, mitigated by the support contract plus a documented internal runbook and a named on-call owner; (2) license drift as the ecosystem's tooling changes hands or terms change, mitigated by tracking the specific license of every component, the core engine, extensions, and backup tooling, in an inventory reviewed at least annually; (3) skills concentration in one or two engineers, mitigated by funding certification and training for a second and third engineer before the first becomes a single point of failure.
Trade-offs & pitfalls
Don't treat open source as automatically cheaper for a regulated client: the audit and compliance overhead of proving controls on a self-assembled stack can exceed a proprietary vendor's bundled compliance tooling, so an honest TCO comparison has to include the cost of building the evidence a regulator will ask for, not just license fees against support fees.
Assess the trade-offs of building a custom search engine, using a managed Elasticsearch service, or adopting a SaaS search provider (e.g., Algolia) for a large e-commerce business. Compare development effort, relevance/control, feature velocity, total cost, data privacy, and scaling characteristics.
Sample Answer
Direct answer
For a large e-commerce business, the default recommendation is a managed Elasticsearch or OpenSearch deployment, not a from-scratch custom search engine and, in most cases, not a pure software-as-a-service (SaaS) product like Algolia. E-commerce search at real scale needs enough relevance customization (custom ranking signals, merchandising rules, complex faceting) that a SaaS product's more bounded configuration surface becomes limiting, while building a search engine from scratch means re-solving a genuinely hard distributed-systems problem the industry already solved well, for no real competitive advantage. Algolia stays the right call specifically when time-to-market and near-zero search-infrastructure operations matter more than deep relevance control, most often for a smaller catalog or a team with no search specialization at all.
Structured elaboration
| Dimension | Build custom | Managed Elasticsearch / OpenSearch | SaaS (Algolia) |
|---|---|---|---|
| Development effort | Very high: you own tokenization, analyzers, ranking, and distributed sharding | Medium: you configure mappings, analyzers, and cluster topology, but the engine itself is built | Low: mostly application programming interface (API) integration and index-schema configuration; ranking and typo tolerance are largely built in |
| Relevance / control | Maximum, but every feature is paid for in engineering time | High: full control over the analyzer and scoring pipeline, including custom scoring scripts | Bounded by Algolia's ranking model and configuration options; real customization exists, but inside their framework, not a scorer you write yourself |
| Feature velocity | Slowest: typo tolerance, synonyms, facets are each their own project | Fast, mature ecosystem, but your team operates and upgrades it | Fastest: new ranking and artificial-intelligence-driven features ship without your team doing anything |
| Total cost of ownership | Highest hidden cost: ongoing specialist engineering headcount indefinitely, rarely justified unless search literally is the product | Infrastructure or managed-service fee plus the operational labor to run it: lower than building, higher than pure SaaS | Usage-based; per Algolia's own published pricing, its Grow tier bills roughly $0.50 per 1,000 search requests and $0.40 per 1,000 records beyond an included allotment, which can grow expensive and hard to predict at large catalog and traffic scale |
| Data privacy | Full control; data never leaves your infrastructure | Full control if self-hosted; some control ceded to the cloud provider on a managed offering | Product and customer data leaves your infrastructure and lives in Algolia's cloud, which matters for regulated data or contractual residency requirements |
| Scaling | You build and prove every scaling mechanism under real load | A proven horizontal scaling model (sharding and replicas) that you tune | Scaling is Algolia's problem operationally, but you're bound by plan tiers and rate limits for burst traffic |
Worked example
Consider a catalog on the order of a few million stock keeping units (SKUs) that needs custom ranking (boosting by margin, inventory availability, and personalization) and complex multi-facet filtering. Per Algolia's current published pricing, its free tier (Algolia has since retired the earlier "Build" tier name) caps out at 10,000 search requests per month and 50,000 records, useful only for a prototype; a catalog of a few million SKUs blows past that record allotment by a factor of 60 or more. Real e-commerce traffic at this catalog size lands on Algolia's pay-as-you-go Grow tier ($0.50 per additional 1,000 search requests beyond the 10,000 included, $0.40 per additional 1,000 records beyond the 100,000 included) or, past a scale Algolia no longer publishes a fixed price for, its custom-quoted Elevate tier. Using Algolia's own current per-unit Grow-tier rates as a back-of-envelope estimate I computed myself, not a vendor-published total: a 3,000,000-record catalog serving 5,000,000 search requests a month works out to roughly $1,160/month in record charges plus roughly $2,495/month in request charges, about $3,655/month combined, before any Elevate-tier volume discount or custom quote even enters the picture. At that spend level, a managed Elasticsearch or OpenSearch cluster sized for the same catalog and traffic typically gives deeper ranking control for comparable or lower ongoing cost, which is what tips the recommendation toward managed Elasticsearch or OpenSearch rather than SaaS for a business at this scale, with "build from scratch" staying off the table entirely unless search relevance is literally the company's core product rather than a supporting feature of it.
Trade-offs & pitfalls
The most common wrong turn is picking a SaaS product early for speed, succeeding, and only later discovering its relevance ceiling once the business has genuinely complex merchandising rules; migrating off a SaaS index to self-run search then means rebuilding ranking logic from a different mental model, not just moving data across. The opposite failure mode is also common: teams that build custom search "because ours is special" almost always underestimate the ongoing cost of keeping tokenization, ranking, and relevance competitive with what an off-the-shelf engine already solved years ago.
Design the data storage architecture for a social feed service with 10M users and 1B posts. Requirements: personalized feeds with p95 read <100ms, write throughput 50k posts/min, support full-text search over posts, and eventual consistency acceptable for feed freshness. Map query patterns (fanout-on-write vs fanout-on-read) to storage options (wide-column, key-value cache, search engine) and justify replication, caching, and consistency trade-offs.
Sample Answer
Direct answer
Use a hybrid fanout: fanout-on-write (push a new post into every follower's precomputed feed at write time) for the vast majority of accounts, and fanout-on-read (pull the author's recent posts at read time and merge them into the feed) for high-follower accounts. Pure fanout-on-write collapses under the write amplification (one write turning into many downstream writes, here one post turning into one inbox write per follower) of a handful of extremely popular accounts, and pure fanout-on-read makes every ordinary read expensive by fanning out a query per followed account at read time.
Structured elaboration
Query pattern to storage mapping.
- Post storage (durable, high write volume, simple key lookup by post id): a wide-column store (Cassandra/Scylla) with replication factor (RF) of 3, a typical durability/availability choice giving each row three replicas so the loss of one node does not lose data, because posts are write-once, read-many and don't need relational joins.
- Precomputed per-user feed ("inbox"): a key-value cache (Redis, or a wide-column "feed" table keyed by user id holding a sorted list of post ids), because a feed read needs to be a single fast lookup by user id, not a fan-out query computed at read time.
- Full-text search over posts: a dedicated search engine (Elasticsearch/OpenSearch), a genuinely different query shape ("rank posts matching these words") that belongs in neither of the above.
Fanout math (worked). 50,000 posts/min is about 833 posts/sec:
posts_per_min = 50_000
posts_per_sec = posts_per_min / 60
avg_followers = 200 # illustrative average, for order-of-magnitude reasoning
naive_fanout_writes_per_sec = posts_per_sec * avg_followers
celeb_followers = 5_000_000
celeb_single_post_fanout = celeb_followers # one post, fanned out synchronously
print(f"posts/sec: {posts_per_sec:.1f}")
print(f"naive fanout-on-write at {avg_followers} avg followers: {naive_fanout_writes_per_sec:,.0f} inbox writes/sec")
print(f"a single post from a {celeb_followers:,}-follower account: {celeb_single_post_fanout:,} inbox writes for ONE post")
posts/sec: 833.3
naive fanout-on-write at 200 avg followers: 166,667 inbox writes/sec
a single post from a 5,000,000-follower account: 5,000,000 inbox writes for ONE post
The steady-state average (about 167,000 inbox writes/sec at this illustrative follower count) is a large but achievable rate for a wide-column store or Redis cluster built for high write throughput. The problem is the TAIL: one post from a 5-million-follower account would generate 5 million inbox writes in one event, dwarfing the steady-state load. For accounts past a monitored follower-count threshold, don't fan out on write; merge their few recent posts into a requesting user's feed at READ time instead, cheap because there are few of them and they are easy to cache. This hybrid is the standard, well-documented pattern large-scale feed systems use for exactly this problem.
Consistency and caching. Eventual consistency is explicitly acceptable per the requirements, so post-create can return immediately while fanout happens asynchronously in a background worker, and Redis in front of the wide-column feed store absorbs the read-hot top-of-feed page (well inside the p95 under 100ms budget; a cache miss falling through to the wide-column store is still fast, single-digit to tens of milliseconds).
flowchart TD
W[New post] --> C[(Cassandra: posts, RF=3)]
W --> F{Author follower count}
F -- normal account --> FW[Async fanout worker]
FW --> Redis[(Redis / wide-column feed store: per-user inbox)]
F -- celebrity account --> Skip[Skip fanout-on-write]
W --> Search[(OpenSearch: async index)]
Reader[Feed read] --> Redis
Reader --> Merge[Merge in celebrity posts at read time]
Trade-offs & pitfalls
The celebrity threshold needs an explicit, monitored cutover, a follower-count boundary that routes an account from fanout-on-write to fanout-on-read, or the hot-write problem reappears in production the first time an ordinary user suddenly goes viral. Full-text search staleness (posts indexed asynchronously) means a just-posted message might not be searchable for a few seconds, acceptable under the stated eventual-consistency tolerance, but worth stating explicitly rather than assuming.
Create an Architecture Decision Record (ADR) outline a junior SA would use to choose between a managed database service (DBaaS) and a self-hosted database for an SMB client. Include sections for context, decision drivers, options considered, trade-offs, decision, consequences, and migration notes.
Sample Answer
Direct answer
An Architecture Decision Record (ADR: a short, versioned document that captures one architectural decision, the reasoning behind it, and what it costs) for this choice should recommend a managed database-as-a-service (DBaaS: a cloud provider that operates the engine, patching, backups, and failover (automatically switching to a standby system if the primary one fails) for you) as the default for a small or midsize business (SMB), because the deciding factor for most SMB clients isn't the database technology, it's whether anyone on staff can be the on-call database administrator, and for a small team the honest answer is usually no.
Structured elaboration
An ADR earns its usefulness from its structure, not its length:
- Context: the situation forcing a decision now (a new service being stood up, a growth trigger, a compliance requirement), described in plain terms a non-technical stakeholder could follow.
- Decision drivers: the small list of things that actually determine the answer (team size and skills, budget, expected growth, uptime requirements), ranked, not just listed.
- Options considered: every option that was genuinely evaluated, including the ones not chosen. An ADR missing rejected options gives a future reviewer nothing to push back on when the decision needs revisiting.
- Trade-offs: what each option costs and gives up, ideally as a short table, so the comparison survives being read without the surrounding prose.
- Decision: the choice, stated as one sentence, with no hedging.
- Consequences: what becomes easier and what becomes harder as a direct result, including things the team is explicitly accepting as a cost.
- Migration notes: what would have to happen to change this decision later, and how expensive that would be, so a future team isn't rediscovering the exit cost from scratch.
Worked example
ADR-014: Managed PostgreSQL vs Self-Hosted PostgreSQL for the Order Management Service
Status: Accepted
Context: We are standing up a new order management service for a 12-person e-commerce SMB client with no dedicated infrastructure or database operations staff. The service needs a relational database for orders, inventory, and payments records.
Decision drivers: (1) no in-house database operations capacity, (2) predictable monthly cost more valuable than the lowest possible infrastructure price, (3) the client's engineers are comfortable with SQL but have never run production failover or point-in-time recovery.
Options considered: (A) a managed PostgreSQL service (automated backups, patching, and failover); (B) self-hosted PostgreSQL on virtual machines, operated by the client's own engineers.
Trade-offs:
| Dimension | A: Managed | B: Self-hosted |
|---|---|---|
| Setup effort | Low, provisioned in under an hour | Higher, requires OS hardening, backup tooling, and monitoring built from scratch |
| Ongoing operational load | Near zero, vendor handles patching and failover | Falls on the client's own engineers, who have no prior production database operations experience |
| Cost | A per-hour service premium over raw compute | Lower raw infrastructure cost, but the engineer-hours to operate it reliably are a real, recurring cost the client is not budgeting for |
| Customizability | Limited to what the vendor exposes | Full control of extensions, OS-level tuning, and configuration |
Decision: Adopt Option A, a managed PostgreSQL service.
Consequences: The client gives up some configuration flexibility and pays a service premium, in exchange for automated backups and failover the client's own team is not currently equipped to build or operate. On-call burden for database availability moves to the vendor.
Migration notes: If the client later hires dedicated operations staff or hits a feature the managed tier doesn't support, the standard PostgreSQL wire protocol and dump/restore tooling keep a future move to self-hosted realistic; budget for a planned migration project rather than an emergency one if that day comes.
Trade-offs & pitfalls
Self-hosted is still the right call when a specific, named requirement rules out every managed option, for example a compliance mandate requiring physical control of the hardware that no vendor will contractually satisfy, or a need for a database extension or version no managed tier offers. The most common mistake a junior architect makes here is writing an ADR that states only the chosen option and skips "options considered" entirely, which reads as a justification written after the fact rather than a decision made with the alternatives genuinely on the table.
You're designing storage for user activity logs that must support (A) ad-hoc analytics and complex queries, and (B) extremely high write throughput with simple access patterns. Compare when to choose a relational database (PostgreSQL) versus a key-value/NoSQL store (DynamoDB). Discuss data model flexibility, transactional guarantees, secondary indexes, scaling patterns, operational cost, and provide a recommended choice for scenario A and scenario B with rationale.
Sample Answer
Direct answer
For scenario A, ad hoc analytics and complex queries, choose PostgreSQL: its SQL vocabulary for joins, aggregates, and window functions, plus general-purpose secondary indexing, directly serves "ask a new question of the data without redesigning the schema." For scenario B, extremely high write throughput with simple, known access patterns, choose DynamoDB: its partition-based architecture scales write throughput close to linearly by spreading load across partitions, without the single-primary ceiling a relational database eventually hits, and "simple access patterns" is precisely the assumption DynamoDB's key design is built around.
Structured elaboration
| Dimension | PostgreSQL | DynamoDB |
|---|---|---|
| Data model flexibility | Fixed schema per table; a JSONB column adds semi-structured flexibility where genuinely needed | Flexible per-item attributes, but the partition key and sort key are effectively fixed once chosen and costly to redesign later |
| Transactional guarantees | Full ACID (atomicity, consistency, isolation, durability), arbitrary multi-row and multi-table transactions, configurable isolation levels | Item-level atomicity always; multi-item transactions across up to 100 items are supported, but without ad hoc joins inside a transaction |
| Secondary indexes | General-purpose indexes addable at any time, supporting arbitrary filter and join predicates | Secondary indexes must be planned around known access patterns ahead of time, and reads against them are eventually consistent by default |
| Scaling pattern | Vertical scaling on the write primary, read replicas for read scale-out; horizontal write scaling needs manual sharding work | Horizontal by design; partitions split automatically as data and throughput grow, giving near-linear write scaling when the key distributes load evenly |
| Query expressiveness | Arbitrary ad hoc SQL: joins, aggregation, group-by, full-text extensions | Lookups against a known key or index; filtering on an attribute outside that key requires a full table scan or a separate analytical system |
| Operational cost shape | Pay for a provisioned instance regardless of traffic shape, and own tuning of vacuum (the background process that reclaims space left behind by deleted or updated rows), bloat (wasted table space vacuum has not yet reclaimed), and connections | Pay per request or per provisioned capacity, no instance sizing, but sustained very high request volume can cost more than an equivalently capable relational instance |
Recommendation with rationale. Scenario A needs query flexibility more than raw write scale. Analysts asking new questions cannot design a key-value schema for a question that does not exist yet, so PostgreSQL, ideally with a dedicated read replica so ad hoc queries do not compete with production writes, fits directly; if analytics volume outgrows what that replica comfortably serves, the next step is exporting into a columnar warehouse, not replacing the log store itself.
Scenario B needs write scaling more than query flexibility. A well-chosen partition key, for example the identifier the events are naturally grouped by, gives near-linear write scaling without a team manually sharding a relational primary, and "simple access patterns" is the exact condition DynamoDB's design assumes rather than fights.
Worked example
Suppose scenario B's target is 50,000 writes per second spread across 100,000 distinct users, a reasonable partition key candidate. That averages 50,000 / 100,000 = 0.5 writes per second per user, far below a single partition's verified ceiling of roughly 1,000 write operations per second for a small item, so a naive per-user partition key absorbs this comfortably. The same 50,000 writes per second against a single relational primary would need careful connection pooling, batched commits, and eventually table partitioning, none of which DynamoDB requires the team to build by hand.
Trade-offs and pitfalls
A pitfall is choosing DynamoDB for scenario A because "it scales." Write scale was never the bottleneck in an ad hoc analytics scenario; query expressiveness was, and a partition-and-key-value model does not fix that.
A pitfall for scenario B is choosing PostgreSQL and assuming sharding can be bolted on later without a real migration project. Relational horizontal write scaling is genuine engineering work, not a configuration flag.
What would flip either recommendation: if scenario A's "ad hoc" queries stabilize into a small, known set, for example always "events for this user in this date range," DynamoDB with a well-chosen sort key handles that fine and more cheaply at scale than PostgreSQL. If scenario B's throughput target turns out to be moderate, a few thousand writes per second, a well-tuned PostgreSQL primary handles it without adopting DynamoDB's operational model at all.
Unlock Full Question Bank
Get access to all Database Selection and Trade-offs interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.