How to design schemas for both OLTP and OLAP efficiently?
Database Developer
answer
Use a hybrid architecture: model core OLTP tables in a normalized, ACID schema (3NF) for fast writes and integrity, then project data to OLAP via change data capture (CDC) into a star/snowflake model. Keep workloads isolated with read replicas or a separate warehouse. Apply bridge tables, type-2 history, and aggregates in the warehouse; expose materialized views for mixed read patterns. This preserves transactional performance while enabling scalable analytics.
Long Answer
Designing a database to handle both transactional (OLTP) and analytical (OLAP) demands clear separation of concerns plus efficient movement of data between shapes optimized for each workload.
1) Model OLTP for correctness and write speed
Keep your system of record in a normalized (3NF) schema: compact rows, foreign keys, strict constraints, and short, indexed transactions. OLTP tables capture current truth (customers, orders, payments) with minimal redundancy to reduce write amplification and anomalies. Use surrogate keys, narrow indexes aligned to the most common point lookups, and row-level locking strategies that avoid hot spots (e.g., append-only order lines instead of upserting aggregates).
2) Don’t force analytics on OLTP
Analytical queries (scans, joins across months of history) compete with OLTP if they run on the same instance. Prevent tail-latency spikes by isolating workloads: either use read replicas for reporting or, better, stream changes into a dedicated warehouse/lakehouse. This preserves p95 write latency and avoids bloated buffer caches from full table scans.
3) Create OLAP-friendly projections
Downstream, remodel into star/snowflake schemas:
- Fact tables (orders, events) with degenerate keys and measured metrics.
- Dimensions (customer, product, date, store) with conformed attributes.
- Slowly Changing Dimensions (SCD2) to preserve history (effective_from/to, is_current).
- Bridge tables for many-to-many (orders↔promotions).
Columnar storage, partitioning by date, and sorted keys minimize scan cost and accelerate group-by and window functions.
4) Move data with CDC instead of batch dumps
Use change data capture (logical decoding, binlog, redo readers) to stream inserts/updates/deletes out of OLTP with minimal overhead. Land raw changes in a staging area, then apply ELT: cleanse, dedupe, and upsert into facts/dimensions with idempotent merge logic. Late-arriving updates and out-of-order events are handled with watermarking and deterministic keys.
5) Serve mixed patterns with safe shortcuts
If product needs near-real-time analytics in the app, expose materialized views (or summary tables) refreshed on a schedule or incrementally via CDC. Keep these read-only to the app; OLTP writes still go to base tables. For hot reads, add read replicas with replica-safe queries (no FOR UPDATE, tolerate replica lag) or CQRS: command endpoints write to OLTP, query endpoints read pre-aggregations.
6) Governance, quality, and lineage
Define contracts between OLTP and OLAP: column meanings, nullability, reference data, and SLOs for freshness. Enforce data quality checks (row counts, uniqueness, referential consistency) in the ELT pipeline. Track lineage so analysts can trace facts back to sources, aiding debugging and compliance.
7) Partitioning, retention, and cost
Partition large OLAP facts by time (daily/weekly) and cluster by join keys. Use tiered storage and retention policies: raw stage for 30–90 days, curated facts long-term, aggregates indefinitely. For OLTP, archive cold rows to history tables to keep working sets small; create covering indexes sparingly to avoid slowing writes.
8) Security and privacy
Propagate row-/column-level masking and PII tokenization from source to warehouse. Apply least privilege: OLTP grants are minimal; analytics users query warehouse views. Keep audit logs for regulatory needs.
9) Performance validation and evolution
Benchmark independently: OLTP with high-concurrency, small transactions; OLAP with wide scans, joins, and group-bys. Monitor p95/p99 latencies, replica lag, CDC end-to-end freshness, and warehouse query cost. As new questions arise, evolve the semantic layer (metrics, dimensions) rather than hitting OLTP directly.
Summary
Model OLTP for correctness and speed; project that truth into OLAP shapes suited for exploration. The glue is low-latency CDC and idempotent ELT. With workload isolation, thoughtfully designed stars, and selective pre-aggregations, you get fast transactions and rich analytics—without the two competing.
Table
Common Mistakes
- Forcing analytics on the OLTP instance, causing lock contention and cache churn.
- Over-indexing OLTP to “speed up reports,” slowing writes and bloat.
- Shipping batch dumps that miss updates/deletes; no CDC means drift.
- Modeling the warehouse as 1:1 copies of source tables—no facts/dimensions, hard joins, poor performance.
- Ignoring SCD2, losing historical truth and breaking cohort/attribution analysis.
- Non-idempotent ELT merges that duplicate facts on retries.
- No workload isolation for read replicas (using FOR UPDATE, not tolerating lag).
- Lack of contracts/lineage; columns silently repurposed break downstream.
- Unbounded retention; runaway costs and slow queries over cold data.
Sample Answers (Junior / Mid / Senior)
Junior:
“I’d keep OLTP normalized with indexes for common queries. For analytics, I’d create read replicas or export data to a warehouse and use summary tables for reports.”
Mid:
“I’d separate workloads: OLTP in 3NF for fast writes, and CDC to a warehouse where I remodel into star schemas with SCD2. Dashboards read materialized views refreshed incrementally. Read replicas handle light reporting; heavy queries run in the warehouse.”
Senior:
“I’d formalize contracts: stable OLTP schemas, CDC to a governed ELT that builds conformed dimensions and fact tables. We’d guarantee freshness SLOs, enforce data quality checks, and expose a semantic layer with metrics. OLTP stays lean (short transactions, selective indexes); OLAP is columnar, partitioned, and cost-managed. For app needs, CQRS + pre-aggregations serve low-latency reads without touching the write path.”
Evaluation Criteria
- Clear separation of OLTP vs OLAP goals and shapes.
- OLTP modeled in 3NF, short transactions, targeted indexes.
- OLAP modeled with facts/dimensions, SCD2, partitions.
- Workload isolation (replicas/warehouse), no heavy scans on OLTP.
- CDC + idempotent ELT with quality checks and lineage.
- Use of materialized views/aggregates for near-real-time reads.
- Security: masking/permissions across both tiers.
- Operational SLOs: tx latency, freshness, cost; monitoring for lag and query performance.
- Awareness of pitfalls: over-indexing, missing deletes, schema drift, retention sprawl.
Strong answers tie modeling choices to measurable performance and reliability outcomes.
Preparation Tips
- Build a mini stack: OLTP (Postgres/MySQL) in 3NF; generate orders/events.
- Set up CDC (logical decoding/binlog) to land changes in a staging table.
- Implement ELT merges to create a star schema: fact_orders, dim_customer (SCD2), dim_product.
- Add materialized views for daily revenue and cohort retention; refresh incrementally.
- Benchmark: OLTP p95 latency under write load; warehouse scan times on partitions vs non-partitioned.
- Break things: late events, out-of-order updates; verify idempotency.
- Add lineage docs and simple data quality tests (row counts, uniqueness).
- Prepare a 60–90s pitch explaining why isolation + CDC + stars beat “one big database for everything.”
Real-world Context
A marketplace ran monthly reports on the OLTP cluster, spiking p99 latency. Moving to CDC → warehouse cut OLTP CPU by 40% and made BI queries 8× faster with partitioned facts. A subscription app lacked SCD2; churn analysis was wrong. After adding SCD2 to dim_customer, cohort metrics stabilized. Another team’s nightly batch missed deletes; duplicate revenue appeared. Switching to idempotent ELT merges and watermarking fixed it. Finally, pre-aggregated materialized views fed product dashboards in seconds, while the system of record stayed lean and predictable—proving that isolation + proper OLAP modeling pays off.
Key Takeaways
- Model OLTP in 3NF for fast, correct writes; keep it lean.
- Use CDC + ELT to project into star schemas with SCD2.
- Isolate workloads (replicas/warehouse); don’t scan OLTP.
- Partition, pre-aggregate, and govern for fast, trusted analytics.
- Validate with freshness, latency, and cost SLOs.
Practice Exercise
Scenario: You’re building a system for an e-commerce app. Product needs real-time dashboards (minutes-fresh) and finance needs accurate month-end reporting—while checkout must remain fast under peak traffic.
Tasks:
- OLTP: Design 3NF tables—customer, product, order, order_line, payment—with concise indexes for point lookups. Keep transactions short; avoid aggregate writes.
- CDC: Stream changes (insert/update/delete) to a staging area with metadata (source table, LSN/offset, op type, event_time).
- ELT: Build dim_customer (SCD2 with effective_from/to), dim_product, dim_date, and fact_order_lines (degenerate order id, net, tax). Implement idempotent merges keyed by (business_key, effective_from).
- Serving: Create materialized views for revenue_by_day and units_by_product with incremental refresh. Partition facts by order_date; cluster by product_id.
- Isolation: Route analytical queries only to the warehouse; expose read replicas to internal tools that must hit OLTP.
- SLOs: OLTP p95 write ≤ 50 ms; warehouse freshness ≤ 5 min; dashboard queries ≤ 2 s. Add data quality checks (row deltas, FK completeness).
Deliverable: A 2-minute walkthrough diagramming OLTP→CDC→ELT→OLAP, explaining how each choice protects OLTP latency and yields trustworthy analytics with minute-level freshness.

