DEV Community

Cover image for Data Lakehouse: How and Why
joni sar
joni sar

Posted on

Data Lakehouse: How and Why

How the data lakehouse works in production — the internal mechanics, the data flow patterns, why tables degrade under real workloads, and the closed-loop control plane that keeps the architecture performing at scale.

What a data lakehouse solves

Every enterprise data platform eventually hits the same wall. Analytical data exists in two places: a data lake (cheap, scalable, ungoverned) and a data warehouse (expensive, fast, governed). Between them sits an ETL pipeline that copies, transforms, and reconciles — creating a permanent tax on engineering time, data freshness, and infrastructure spend.

The symptoms are familiar. Dashboards show yesterday's numbers because the warehouse loads overnight. ML models train on stale copies because the warehouse does not support Python-native access. Storage bills grow because the same curated datasets live in both systems simultaneously. Governance fragments because access controls, lineage, and audit trails cannot span two architecturally different platforms.

The data lakehouse resolves this by collapsing both systems into one: transactional guarantees applied directly to data on object storage. One copy. One governance model. Any engine — SQL, ML, streaming, AI — reads and writes the same tables with full ACID safety. The warehouse is not replaced by a different product; the lake becomes the warehouse through a metadata innovation called a table format.

The practical result: BI dashboards, Spark ML pipelines, Flink streaming jobs, and autonomous AI agents all query the same governed tables — without ETL between them, without stale copies, without paying warehouse markup on storage that costs $0.023/GB/month in its native form.

The internal mechanics: how a lakehouse actually works

A data lakehouse is not a monolithic system. It is four cooperating layers — each handling a specific responsibility, each independently evolvable. Understanding how they interact is the foundation for building one that performs in production.

The storage layer

All data resides on cloud object storage — S3, GCS, or ADLS. This is where the economics originate. Object storage provides eleven-nines durability at $20–25 per TB per year. A petabyte of analytical data costs roughly $20,000/year to persist — compared to $500,000+ when that same data sits inside a traditional warehouse with bundled compute.

Storage is decoupled from everything above it. Shut down every query engine and the data remains. Add a new engine tomorrow — it reads from the same bucket. Move clouds — the files copy byte-for-byte with no format conversion.

Data lands as Apache Parquet files — a columnar format that stores values by column rather than by row. A query touching 5 columns from a 300-column table physically reads only those 5 columns. Parquet also embeds per-column min/max statistics in each file header, enabling query engines to skip entire files whose value ranges cannot satisfy the WHERE clause. This skip-scanning is what makes lakehouse queries competitive with warehouse queries — but only when files are properly sized and organized.

The table format layer

A directory of Parquet files on S3 is a data lake — readable, but not transactional. The table format is the metadata innovation that adds the missing guarantees:

Apache Iceberg — the dominant format as of 2026, supported natively by Spark, Trino, Flink, DuckDB, Snowflake, Databricks, Athena, and StarRocks — provides ACID commits, schema evolution, time travel, partition evolution, and concurrent multi-writer safety through a metadata tree architecture.

How the metadata tree works:

Each Iceberg table maintains a hierarchy of metadata files on the same object storage as the data:

  1. A metadata pointer (tracked by the catalog) — points to the current table version
  2. Snapshot files — each representing the table's complete state at a point in time. Every write creates a new snapshot.
  3. Manifest lists — each snapshot references a manifest list that indexes the active manifests
  4. Manifests — each tracking a batch of data files with per-file statistics (path, partition values, row count, column min/max)
  5. Data files — the actual Parquet files containing rows

This tree enables two properties that make the lakehouse viable:

Atomic commits. Every write produces new data files and a new snapshot. The catalog atomically swaps the pointer from old snapshot to new. Readers always see a consistent state. Failed writes leave no trace — the pointer was never advanced.

Statistical pruning. Query engines read manifests (kilobytes) to determine which data files (gigabytes) are relevant. A query filtering on country = 'DE' checks manifest-level statistics and skips every file whose country column's min/max range excludes 'DE'. No data read. No I/O wasted. This is why lakehouse queries can match warehouse speed — but only when the metadata is current and the data layout aligns with query patterns.

The critical implication: every commit grows the tree. Every streaming write adds files. Every mutation adds delete markers. The tree that enables fast queries also accumulates entropy that degrades query speed over time — unless something actively maintains it.

The catalog layer

The catalog is the coordination service that answers: where is the current metadata pointer for each table, and how do multiple engines safely coordinate writes?

Every engine — Spark, Trino, Flink, DuckDB — consults the catalog before each read (to locate current metadata) and during each write (to commit atomically). Without the catalog, concurrent writers could corrupt table state. With it, they race safely: one commits, the other retries against updated state.

Modern lakehouses use the Iceberg REST Catalog specification — a standard HTTP API that every engine implements. This means adding a new engine is a configuration change (point it at the catalog URL), not an integration project. Catalog options include managed services (AWS Glue), open-source servers (Apache Polaris, Lakekeeper), federated solutions (Apache Gravitino), and Git-branching models (Project Nessie) — all speaking the same REST protocol.

The catalog is also where access control, retention policies, and audit logging materialize. It is the governance anchor for multi-engine environments where every engine must see consistent permissions.

The compute layer

The lakehouse separates compute from storage, enabling multiple specialized engines to operate on the same data concurrently:

  • Spark — batch ETL, ML training, complex multi-stage transformations. The workhorse for heavy writes and joins.
  • Trino — interactive SQL with sub-second response times. Excels at dashboard queries and ad-hoc exploration.
  • Flink — streaming ingestion with exactly-once semantics. Continuous CDC from operational databases into lakehouse tables.
  • DuckDB — embedded analytics for notebooks, CI/CD pipelines, and single-node processing. Zero infrastructure overhead.
  • Snowflake / Athena / StarRocks — managed engines for specific workload profiles (high-concurrency BI, serverless ad-hoc, real-time OLAP).

Each engine discovers tables through the same REST catalog and reads/writes through Iceberg's transactional protocol. They coexist safely on the same tables through snapshot isolation. This is the key architectural advantage over the warehouse model: instead of one vendor's engine for everything, you use the best tool for each workload shape.

But multi-engine access multiplies operational pressure. More engines means more write patterns, more file fragmentation profiles, and more divergent query patterns competing for the same table's physical layout — creating the operational challenge that defines production lakehouse management.

How data flows through a production lakehouse

Theory aside — how does data actually move from source systems through the lakehouse to consumers? The medallion architecture (bronze → silver → gold) is the standard pattern for organizing this flow, and each layer creates different operational characteristics that matter for long-term health.

Bronze: the raw capture layer

Source data lands in its original form. CDC events from PostgreSQL (captured by Debezium, written by Flink). Clickstream events from Kafka. Daily batch exports from SaaS APIs. Partner file drops. Everything arrives as append-only, schema-on-read, immutable records.

Bronze is the replay source. When silver-layer transformation logic has a bug discovered months later, you rebuild from bronze. When a new use case requires fields that were previously ignored, they are already preserved in bronze. This immutability is non-negotiable — teams that apply transformations at ingestion lose the ability to retrospectively correct logic errors.

Common bronze ingestion patterns:

  • Streaming CDC — Debezium captures row-level changes (inserts, updates, deletes) from PostgreSQL, MySQL, or MongoDB. Flink consumes these events and writes them to Iceberg tables with exactly-once semantics at sub-minute commit intervals. Each commit is small (a few thousand rows) but creates a new data file and a new snapshot.
  • Event streams — Application events (clickstreams, transactions, IoT sensor data, ad impressions) flow from Kafka topics into Flink or Spark Structured Streaming jobs that write to Iceberg. Event volumes are high and bursty — Black Friday traffic spikes create 10x the normal file accumulation rate.
  • Batch loads — Daily or hourly exports from ERP systems, CRM platforms, and third-party APIs. These produce larger files but less frequently. Batch tables fragment slower but still accumulate snapshot overhead.
  • File drops — Partners or internal systems deposit CSV/JSON/Parquet files in S3. A detection pipeline validates schema, converts to Iceberg-managed Parquet, and registers the files in the catalog.

What this means operationally: Streaming CDC with 5-minute commits creates approximately 8,600 new files per table per month. A lakehouse ingesting from 20 operational databases at sub-minute latency accumulates hundreds of thousands of files across its bronze layer within weeks. Individual file sizes average 5–20 MB — far below the 256–512 MB target where engines perform optimally. File count — not data volume — is what degrades query planning speed.

Silver: the governed truth layer

Silver transforms bronze into a data model that the organization commits to: one row per entity, resolved foreign keys, deduplicated events, enforced types, quarantined bad records. Silver is not a cleanup step — it is an architectural commitment to a domain model that all downstream consumers depend on. If a table exists because one dashboard needs a specific aggregation, it belongs in gold, not silver.

Key transformations:

  • Deduplication — Late-arriving records, duplicate events from at-least-once delivery, and replay scenarios resolved to a single authoritative version. Deduplication runs as MERGE INTO with match conditions, producing delete markers for superseded records.
  • Type enforcement and validation — Strings cast to proper types. Nulls validated against business rules. Referential integrity checked against dimension tables. Records failing validation quarantined to error tables with reason codes — never silently dropped, never propagated downstream.
  • Slowly changing dimensions (SCD Type 2) — History tracked for entities that evolve over time. When a customer's tier changes, the old row is closed (end_date set) and a new row opened. This produces update operations on every change event.
  • Reference data enrichment — Raw IDs joined to meaningful attributes. Country codes resolved to names. Product SKUs expanded to categories, brands, and pricing tiers. Enrichment creates wider rows with higher value per query.
  • Temporal alignment — Events from different sources (orders, payments, shipments) aligned to consistent time zones, granularity, and business calendars.

Silver tables are the enterprise source of truth. Every downstream consumer — dashboards, ML models, AI agents, compliance reports — starts from the same clean, governed layer.

What this means operationally: Silver tables receive MERGE INTO operations — upserts that create delete markers (position-delete files or V3 deletion vectors) that every subsequent read must reconcile. A CDC table receiving 50,000 updates per hour generates thousands of delete markers per day. Query engines must read both the data files and the delete files, reconcile which rows are current, and filter accordingly — adding I/O overhead that increases linearly with delete-file count. Without periodic resolution of these markers, query latency creeps 2–5x higher while the table reports the same row count and appears unchanged to basic monitoring.

Gold: the consumer-optimized layer

Gold tables exist for performance: pre-aggregated metrics for dashboards, denormalized feature tables for ML training, materialized snapshots for compliance reporting. Gold trades storage redundancy for read speed — accepting wider tables and duplicated columns to eliminate joins at query time.

Gold layer patterns:

  • BI aggregations — Daily/weekly/monthly rollups pre-joined by all relevant dimensions. A dashboard that previously ran a 30-second join across 5 silver tables now reads a single pre-materialized gold table in under 1 second.
  • ML feature tables — Wide, denormalized tables with one row per entity and all features materialized. Training jobs read a single scan rather than orchestrating multi-table joins. Feature freshness controlled by the gold refresh cadence.
  • Compliance snapshots — Point-in-time materializations capturing exactly what was known at a specific date. Regulatory filings, board reports, and audit evidence stored as immutable gold snapshots with indefinite retention.
  • Serving tables — Pre-computed results for user-facing analytics (product recommendations, customer health scores, real-time dashboards) with sub-second SLA requirements.

What this means operationally: Gold tables are typically overwritten on a schedule — daily, hourly, or triggered by upstream freshness signals. Each OVERWRITE operation atomically replaces the table's content: it writes new data files, creates a new snapshot pointing to them, but leaves the previous snapshot's files in storage until explicitly expired. A daily gold refresh creates 365 snapshots per year. At 50 GB per refresh, that is 18 TB of stale data files persisting in storage — even though only the latest 50 GB is logically current. Without snapshot lifecycle management, storage grows linearly forever from data that was replaced weeks or months ago.

The maintenance gradient

The three layers create a gradient of operational need:

  • Bronze → small-file pressure (compaction priority)
  • Silver → delete-file pressure (merge resolution priority)
  • Gold → stale-snapshot pressure (expiration priority)

No uniform maintenance schedule handles this correctly. Each table needs the right operation at the right cadence — determined by its ingestion velocity, mutation pattern, and query load. This is the insight that leads directly to the control plane model.

What the lakehouse unlocks: multiple workloads, one platform

The economic case (10–50x cheaper storage) is straightforward. The architectural case is more powerful: eliminating the boundaries between workload types that the two-system model enforced.

BI and reporting

Dashboards query silver and gold tables directly through Trino or Snowflake. No warehouse sync delay. No overnight ETL window creating stale numbers. Schema changes in silver propagate to consumers without separate migration scripts — because the table format handles schema evolution as a metadata-only operation.

Time travel lets analysts reproduce the exact state of any report at any prior date. In regulated industries (financial services, healthcare, insurance), "what did we report last quarter" must be answerable precisely and auditably. The lakehouse provides this natively through snapshot pinning — no separate archival infrastructure required.

Performance depends on table health: well-compacted tables with accurate column statistics and sort-order alignment with dashboard filter patterns enable engines to prune 90%+ of files on selective queries. When a BI dashboard filters on region = 'EMEA' AND quarter = 'Q2', a properly maintained table skips every file that cannot contain matching rows. A degraded table forces a full scan regardless of how selective the filter is. This is why maintenance directly impacts end-user experience — and why it cannot be deferred.

ML and feature engineering

ML pipelines read training data from the same governed tables that power dashboards — eliminating training-serving skew, the most common source of ML model degradation in production. When the training pipeline and the serving pipeline read from different copies (one from the warehouse, one from the lake), subtle differences in transformation logic cause the model to encounter data distributions in production that it never saw during training. The lakehouse eliminates this by providing one table for both.

Experiment reproducibility comes free: pin to a snapshot ID, retrain on byte-for-byte identical data months later. Feature freshness improves because features and serving data live in the same transactional system — no nightly export, no stale copies, no drift between what the model trained on and what it serves against.

Feature stores built on lakehouse tables inherit versioning, access control, lineage, and time-travel capabilities from the table format. Feature computation runs as standard Spark or Flink jobs writing to Iceberg tables — no separate feature-store infrastructure, no proprietary feature format.

Streaming analytics

Flink and Spark Structured Streaming write directly to lakehouse tables with exactly-once transactional guarantees. Near-real-time dashboards and alerting read from the same tables — no separate streaming infrastructure, no Kafka-to-materialized-view pipeline, no divergent dual-path architecture.

The same transformation logic runs as streaming (for freshness) or batch (for cost) by changing only the trigger configuration. This eliminates the lambda architecture's core problem: maintaining two parallel pipelines (one batch, one stream) with identical logic that inevitably drift apart. In the lakehouse model, there is one pipeline with a tunable latency/cost knob.

AI agents as first-class consumers

In 2026, AI agents autonomously discover schemas, formulate analytical queries, and feed results into multi-step reasoning chains. The lakehouse is their knowledge infrastructure — providing structured, governed, queryable data that agents access through standard protocols.

The requirements for agent access differ from human access: agents generate unpredictable query patterns, cannot diagnose slow responses caused by table degradation, and burn tokens (and money) on retries when they hit poorly-maintained tables. They also need guardrails — limits on what they can read, how much they can scan, and what they can modify.

Why lakehouses degrade: the operational reality

Here is what most guides skip. The four layers give you the architecture. They do not give you a system that stays healthy. Every production lakehouse — without exception — degrades over time unless something actively maintains it. This is not a flaw; it is a consequence of how append-only transactional systems work.

The mechanics of degradation

Iceberg never modifies files in place. Every write creates new files. Every snapshot preserves a complete view. This is what provides transactional safety — but it means the system accumulates structural debt continuously:

File fragmentation. Each commit adds files. Streaming ingestion at 5-minute intervals into a table receiving 2 GB/hour creates ~8,600 files per month. Each file averages 12 MB — well below the 256–512 MB target where query engines perform optimally. The engine must open, plan, and coordinate reads across 100x more files than necessary.

Planning overhead. Engine query planners traverse the manifest tree to identify relevant files. At 1,000 files, planning takes milliseconds. At 50,000 files, planning takes 10–20 seconds — sometimes exceeding the query execution itself. The metadata hierarchy that enables fast pruning becomes a bottleneck when it indexes too many undersized files.

Delete-file accumulation. Every UPDATE and DELETE writes markers that subsequent readers must reconcile against data files at read time. A heavily-mutated table (CDC, SCD, late-arriving corrections) accumulates thousands of delete markers. Query latency increases 2–5x while the table's row count and size appear unchanged — making degradation invisible to basic monitoring.

Storage waste. Expired logical content leaves physical files behind. Orphaned files from failed writes, aborted compaction, and expired snapshots accumulate in storage. Without active cleanup, production lakehouses accumulate terabytes of unreferenced files — pure cost with no analytical value.

Compounding pressure. These four forces are not independent — they compound. More files means larger manifests. Larger manifests means slower planning. Slower planning means longer maintenance operations. Longer maintenance operations means less frequent runs. Less frequent runs means more file accumulation. The system has a natural tendency toward runaway degradation that accelerates once it begins.

Why manual maintenance does not scale

The instinct is to write scripts: a Spark job that compacts every table nightly, a cron that expires old snapshots weekly. This works for 5–10 tables. It fails at production scale for structural reasons:

Tables need different cadences. A streaming table needs compaction hourly. A daily-refresh table needs it weekly. A slowly-growing dimension needs it monthly. One schedule cannot serve all three without either wasting compute on healthy tables or neglecting degraded ones.

Operations have dependencies. Compacting files that will be expired next hour is wasted work. Rewriting manifests before compaction invalidates the rewrite. Computing statistics on pre-compaction layouts produces stale metadata. The five maintenance operations must run in a specific sequence — and re-sequence when conditions change.

Maintenance competes with production. Running compaction on the same Spark cluster that serves production queries creates resource contention. Running it concurrently with active writers on the same table causes commit conflicts. Scheduling around production windows requires coordination that scripts cannot perform.

Static thresholds drift. "Compact when file count exceeds 1,000" is reasonable for one table's current state. But partition cardinality changes, ingestion velocity shifts, query patterns evolve. The threshold that was correct last month is wrong today — and nobody adjusts it until the table is already degraded.

The control plane: a closed-loop system

The answer is not better scripts or more sophisticated cron. It is an architecturally different approach: a control plane that operates the lakehouse as a closed-loop system — continuously sensing table state, reasoning about what each table needs, executing the right operations in the right sequence, and learning from outcomes to improve future decisions.

    ┌──────────────────────────────────────────────────────┐
    │                                                      │
    │   SENSE  →  ASSESS  →  PLAN  →  EXECUTE  →  LEARN   │
    │     ↑                                         │      │
    │     └─────────────────────────────────────────┘      │
    │                (continuous per table)                 │
    │                                                      │
    └──────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

This is the mental model for LakeOps — an autonomous control plane for data lakehouses that implements this closed loop across every table in your lake, continuously, without cron jobs or manual intervention.

Sense: collecting structural telemetry

The control plane continuously reads metadata from every connected catalog — file counts per partition, file size distributions, manifest depth, snapshot velocity, delete-file ratios, partition-level skew, and cross-engine query patterns. This is metadata inspection, not data access — the control plane never reads or moves your actual data.

The sensing is passive and lightweight. It adds no load to production engines. It works across catalogs (Polaris, Glue, Gravitino, Nessie, Lakekeeper) and across engines (Spark, Trino, Flink, DuckDB, Snowflake, Athena) — aggregating a unified view that no single component can provide alone.

Assess: health classification

Raw telemetry becomes actionable through health scoring. Every table is continuously classified:

  • Healthy — file sizes within target, manifests compact, delete ratios low, sort order aligned with query patterns. No action needed.
  • Warning — metrics drifting toward thresholds. File count growing. Delete ratio increasing. Not yet impacting queries — but will if left unaddressed.
  • Critical — active degradation impacting performance. Planning latency elevated. Read amplification high. Immediate maintenance required.

The thresholds are not static defaults. They account for each table's partition cardinality, ingestion velocity, engine mix, and historical maintenance response — adapting automatically as workloads evolve.

LakeOps observability surfaces this classification as a lake-wide dashboard: how many tables are healthy, warning, critical — with drill-down into specific metrics, proactive insights at severity levels, and cross-engine telemetry that reveals optimization opportunities no single engine can see.

Plan: sequenced maintenance decisions

For each table classified as Warning or Critical, the control plane determines which operations to run and in what order.

The sequencing is not arbitrary — it follows a dependency chain where each step's output becomes the next step's input:

Step 1 → Expire snapshots. Remove snapshots beyond the retention policy. This dereferences files that are no longer needed — reducing the scope for subsequent operations and preventing compaction from processing files about to be garbage-collected.

Step 2 → Remove orphan files. Delete unreferenced files older than the safety window (default: 7 days, configurable). This captures files newly dereferenced by expiration, plus accumulated waste from failed writes and aborted operations.

Step 3 → Compact data files. Merge small files into optimally-sized ones. Resolve delete markers so subsequent reads skip reconciliation overhead. Optionally sort data by query-relevant columns to enable statistical pruning.

Step 4 → Rewrite manifests. Consolidate the manifest tree to reflect the new compacted layout. After compaction reduces file count from 50,000 to 2,000, the manifest tree should reflect 2,000 files — not carry forward metadata from the old layout.

Step 5 → Compute statistics. Refresh Puffin column statistics (distinct values, null counts, extended min/max) on the compacted files. This ensures every engine benefits from accurate metadata for pruning decisions.

LakeOps managed maintenance runs this five-step pipeline as a coordinated sequence per table — respecting dependencies, avoiding conflicts with active writers, and targeting only the partitions that need work.

Execute: fast, conflict-aware action

The control plane executes maintenance on a purpose-built engine rather than borrowing production compute:

LakeOps compaction runs on a dedicated Rust binary powered by Apache DataFusion — not Spark. The practical differences:

  • Speed: A 1 TB TPC-DS compaction benchmark completes in under 4 minutes — roughly 29x faster than equivalent Spark operations on the same data. This speed means maintenance runs in minutes rather than hours, so tables never accumulate enough debt to degrade between cycles.
  • Cost: Sub-$5 per TB compacted — roughly 90% cheaper than running equivalent Spark clusters. This economic efficiency is what makes continuous compaction viable rather than forcing teams into overnight-only windows.
  • Reliability: Bounded memory with graceful spill-to-disk. No JVM garbage collection pauses. No OOM crashes on large tables. No cluster provisioning delay.
  • Conflict safety: Aware of active writers and in-flight transactions. Never compacts partitions with concurrent writes. Never expires snapshots that active readers depend on.

Intelligent sort: learned from production queries

Beyond file consolidation, LakeOps compaction physically sorts data by the columns that production queries actually filter on — learned automatically from cross-engine telemetry.

This is the highest-leverage optimization in the entire stack. When data within each file spans a narrow value range for the sort columns, statistical pruning becomes surgical: the engine checks file-level min/max metadata and eliminates 90%+ of files before reading any data. The difference between an unsorted table (full scan on every query) and a properly sorted table (targeted reads on 5–10% of files) is typically 8–12x in query speed.

The key insight is that the right sort order is not static. Trino queries might filter on customer_id and order_date. Spark ML pipelines might filter on event_type and region. AI agents might filter on combinations nobody predicted. No single engine has the full picture of how the table is accessed. The control plane aggregates telemetry from all engines and computes the optimal sort strategy for the combined workload — updating it automatically as patterns shift over time.

Learn: outcome-driven improvement

After each maintenance cycle, the control plane measures outcomes against expectations. Did file count reach the target? Did planning latency improve? Did the health score advance? Results feed back into the assessment model:

  • Tables that responded well to sort compaction on specific columns get those columns reinforced in future cycles
  • Tables where expiration freed significant storage get more aggressive retention recommendations
  • Tables where manifest rewriting dramatically improved planning get lower rewrite thresholds

This learning loop means the control plane improves over time — each cycle's outcomes inform the next cycle's decisions. Tables with unusual characteristics (very high partition cardinality, extremely bursty ingestion, mixed engine access) get customized strategies without manual configuration.

Governance: policies that run themselves

Visibility without enforcement is just monitoring. The control plane turns observability into automated governance through declarative policies:

LakeOps governance supports policies at multiple scopes:

  • Organization-wide defaults — baseline compaction targets, snapshot retention, orphan cleanup schedules applied to every table unless overridden
  • Namespace-level rules — production namespaces get aggressive maintenance; staging gets relaxed thresholds
  • Per-table exceptions — compliance tables with 365-day retention; hot tables with 15-minute compaction cadence

Policies inherit downward: new tables automatically receive the governance rules of their namespace. No manual configuration per table. No tables falling through the cracks because someone forgot to add them to the maintenance script.

Every policy execution is logged with full audit trail — what ran, when, what changed, duration, bytes before/after. This is critical for compliance environments where "prove your data lifecycle management" is a regulatory requirement.

Query routing: making multi-engine economically rational

Having multiple engines on the same data is architecturally elegant. But without routing intelligence, it becomes accidentally expensive: queries dispatched to the wrong engine pay the wrong pricing model and get the wrong performance profile.

A point lookup for 100 rows dispatched to Spark burns 30 seconds of cluster startup. That same query on DuckDB resolves in 0.3 seconds. A dashboard query running on Snowflake at $2/credit is 10x more expensive than the same query on a self-hosted Trino cluster. A full-table scan on DuckDB crashes; on Spark, it completes in minutes.

LakeOps query routing provides a single SQL endpoint that dispatches queries to the optimal engine based on:

  • Workload type — define routing groups (BI/Reporting → cost-optimized, Data Science → performance-optimized, ETL → throughput-optimized) with different backend engine pools
  • Table health state — well-compacted tables are eligible for lightweight engines (DuckDB, Athena). Fragmented tables route to engines that tolerate planning overhead (Spark).
  • Cost/latency targets — constraints per group that the router respects (under $0.05/query for BI, under 2s latency for dashboards)

The routing layer and the maintenance layer form a reinforcing loop: as the control plane compacts and sorts tables, more engines become eligible per query shape. More routing options mean lower per-query cost. Lower cost justifies more frequent querying. More frequent querying generates better telemetry for compaction decisions.

AI agent enablement: the lakehouse as knowledge infrastructure

In 2026, AI agents are not just consumers of pre-built reports — they autonomously explore data, formulate queries, and feed results into reasoning chains. The lakehouse becomes the knowledge layer that agents operate on.

This creates specific requirements that a control plane addresses:

Access interface. LakeOps provides an MCP-native interface (Model Context Protocol) with PostgreSQL, MySQL, and Arrow Flight wire compatibility. Any MCP-compatible agent discovers catalogs, browses schemas, executes queries, and receives results — without custom integration per agent framework.

Layered guardrails. Agents need boundaries. The control plane enforces per-session constraints:

  • ReadOnly — blocks DDL and DML; agents explore but cannot modify
  • CostEstimate — rejects queries whose estimated scan exceeds configurable thresholds
  • PIIMask — hashes sensitive columns before results reach the model
  • HumanApproval — pauses high-stakes operations for human review before execution

Closed-loop optimization. Agent query telemetry feeds back into the control plane's sort and compaction decisions. Tables that agents query heavily get optimized for agent access patterns. The lake adapts to AI workloads without manual intervention — queries get faster as agents use the system more.

Implementing: the practical sequence

You do not need the full architecture on day one. Each step delivers independent value and sets up the next:

1. Start with Iceberg. Choose Apache Iceberg for all new analytical tables. The ecosystem support is universal — every major engine reads and writes it natively. Existing Delta Lake tables interoperate through UniForm.

2. Deploy a REST catalog. This is the coordination point — get it right early. AWS Glue for managed simplicity. Self-hosted Polaris for full control. Gravitino if you need to federate across existing catalogs.

3. Build the ingestion layer (bronze). CDC from operational databases via Flink. Event streams from application telemetry. Batch loads from external sources. Keep it append-only and immutable.

4. Build the semantic layer (silver). Domain modeling, deduplication, quality enforcement. This becomes the organization's governed truth — every downstream consumer starts here.

5. Connect the control plane. Once data flows and tables accumulate, connect LakeOps to your catalog. Ten minutes, no data movement, no infrastructure changes. Instant visibility into every table's health state. Start in manual-approval mode — review what the control plane recommends before enabling autonomous execution. Then enable autopilot and let the closed loop run.

6. Add specialized engines. As workloads diversify, add Trino for interactive SQL, DuckDB for notebooks, Snowflake for governed BI access. The REST catalog makes each addition a configuration step.

7. Build consumer-optimized tables (gold). Pre-aggregations, feature tables, reporting snapshots. Optimize for specific access patterns once you understand what consumers need.

8. Enable routing. With 3+ engines, define routing groups. Let the control plane dispatch each query to the optimal backend automatically.

9. Open AI access. Expose tables to agents via MCP. Configure guardrails per agent type. Agent telemetry feeds back into optimization priorities.

Comparing the options: lake, warehouse, lakehouse

Characteristic Data lake Data warehouse Data lakehouse
Storage model Open files on object storage Proprietary format, vendor storage Open files on object storage
Transactions None Full ACID Full ACID (table format)
Governance Manual, fragmented Vendor-managed, centralized Catalog-unified, multi-engine
Query speed Depends entirely on maintenance Vendor-optimized, consistent Matches warehouse when maintained
Engine flexibility Any tool reads files Vendor's engine only Multiple engines, REST catalog
ML/AI workloads Native but ungoverned Export required Native and governed
Streaming Separate infrastructure Separate infrastructure Same tables, same transactions
Cost at petabyte ~$20K/yr storage ~$500K+/yr storage+compute ~$20K/yr storage + operations
Maintenance burden None (no transactions) Zero (vendor manages) Requires control plane
Vendor lock-in Low High Low (open formats + catalog)

The lakehouse occupies a specific position: warehouse guarantees at lake economics, with the trade-off that operational maintenance is your responsibility rather than a vendor's. The control plane is what makes this trade-off viable at scale — providing the vendor-grade operational ease without the vendor lock-in.

The economic model

The lakehouse's cost advantage operates at four levels that compound:

Level 1: Storage decoupling. Object storage at $20–25/TB/year vs. warehouse storage at $500–2,000/TB/year. For 200 TB of curated data, that is $4,000–5,000/year vs. $100,000–400,000/year. At petabyte scale, the savings fund entire platform teams. But storage cost is only the starting point — the larger savings come from operational efficiency.

Level 2: Elimination of duplication. The lake-to-warehouse ETL that copies, transforms, and reconciles data disappears. This eliminates: the compute cost of the ETL pipeline itself, the engineering hours maintaining it, the storage cost of the warehouse copy, and the reconciliation overhead when copies drift. For a 200 TB estate, duplication elimination saves $100K–400K/year in direct warehouse storage costs plus 1–3 FTEs worth of engineering time maintaining the pipeline.

Level 3: Multi-engine routing efficiency. When every query runs on the cheapest engine that meets its latency requirement, aggregate compute cost drops dramatically. A DuckDB point lookup costs fractions of a cent. A self-hosted Trino dashboard query costs pennies. A Spark batch join costs proportional to actual data processed. Without routing, organizations default to Snowflake pricing for everything — $2+ per credit regardless of query complexity. With routing, simple queries route to lightweight engines and only expensive workloads pay for expensive compute.

Level 4: Maintenance economics. The control plane's Rust-based engine compacts at sub-$5/TB — roughly 90% cheaper than equivalent Spark maintenance clusters. This cost reduction is not incremental — it is structural. It makes continuous maintenance economically viable rather than forcing overnight-only windows where tables degrade for 23 hours between passes. Continuous maintenance means tables never accumulate enough degradation to require expensive recovery operations, queries never slow enough to warrant over-provisioned clusters as compensation, and engineering teams never spend emergency weekends rebuilding collapsed tables.

Level 5: Recovered engineering time. Without autonomous operations, platform teams spend 20–40% of their capacity on table health — writing maintenance scripts, debugging failures, tuning thresholds, responding to "the dashboard is slow" tickets. With a control plane handling the closed loop, that time returns to building data products, onboarding new sources, and serving consumers. For a five-person platform team, that is 1–2 engineers' worth of recovered capacity.

Combined impact: Organizations operating at 500+ TB report 3–5x total cost reduction compared to the warehouse-plus-lake architecture — combining storage savings, duplication elimination, routing-driven compute efficiency, cheaper maintenance, and recovered engineering time.

When to build a data lakehouse

Not every team needs this architecture. A single-engine, single-workload team at moderate scale gets reasonable value from a managed warehouse without the operational complexity. But the lakehouse becomes the correct choice when:

  • Multiple workload types coexist. BI, ML, streaming, and AI workloads need the same data with different access patterns and different engines.
  • Scale makes economics matter. Above 50–100 TB of analytical data, the storage cost differential (10–50x) between warehouse and lakehouse becomes significant enough to fund an entire platform team.
  • Multi-engine is a requirement. Different teams or workloads genuinely need different engines — Spark for ETL, Trino for interactive, Flink for streaming, DuckDB for development. The lakehouse makes this safe; the warehouse makes it impossible.
  • Vendor independence is a priority. Open formats on your own storage mean no single vendor controls your exit path. Every component decision is reversible.
  • Data freshness matters. Streaming ingestion directly into governed tables eliminates the ETL delay that warehouses impose between source and dashboard.
  • AI/ML is a first-class workload. Models and agents need native, governed access to analytical data — not exports, not API wrappers, not stale copies in separate feature stores.

If three or more of these apply, the lakehouse is not a future consideration — it is the architecture to build toward now.

Conclusion

The data lakehouse is not a concept — it is the production standard for teams that need BI, ML, streaming, and AI on the same governed data without warehouse pricing or lake-quality compromises.

Building one is an assembly problem: object storage for economics, a table format (Iceberg) for transactional guarantees, a REST catalog for coordination, and specialized engines for execution.

Operating one is a systems problem: tables degrade through file fragmentation, metadata growth, delete-file accumulation, and storage waste. Bronze layers fragment through streaming commits. Silver layers accumulate delete-file debt through mutations. Gold layers waste storage through stale snapshots. The degradation is inherent to append-only transactional design — not a bug to fix but a force to continuously counteract.

The control plane is the system that counteracts it. LakeOps implements the closed loop — sense structural telemetry across every table and catalog, assess health with adaptive scoring, plan sequenced maintenance respecting operation dependencies, execute on a dedicated Rust engine that is fast enough to run continuously, and learn from outcomes to improve future decisions. Intelligent compaction that sorts by production query patterns across all engines. Sequenced maintenance that runs the right operations in the right order. Observability that classifies every table's health and surfaces degradation before users feel it. Routing that dispatches queries to the optimal engine for each workload. Governance that enforces retention, maintenance, and access policies lake-wide without per-table configuration. And AI enablement that makes the lake agent-ready with discoverable schemas and layered guardrails.

The architecture works because something continuously keeps it working. That something is the control plane.

Thanks for reading!


Further learning:

Top comments (0)