Section B · Architecture foundations

Reference Architectures Compared

Three end-to-end reference stacks — open-source lakehouse, Databricks-centric, and Snowflake-centric — drawn as full pipelines for GridDP and compared at every layer. The goal of this chapter is to make the choice legible: not "which tool is best," but "given this team, this capital model, and this telemetry firehose, which slots do I fill with what, and where do I stop arguing and just pick."

The seven capabilities every architecture has

Before naming a single product, internalize this: a data platform is not a pile of tools, it is a set of capabilities that must be filled somehow. Every architecture — Snowflake, Databricks, a hand-rolled open-source lakehouse, or the platform inside Google — fills the same seven slots. The vendors differ only in how many slots one product covers and how tightly those slots are welded together.

┌──────────────────────────────────────────────────────────────────────────┐ │ THE SEVEN CAPABILITIES (vendor-neutral) │ │ │ │ sources ──▶ ① INGEST ──▶ ② STORE ──▶ ③ TRANSFORM ──▶ serve ──▶ consumers │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ ① INGEST │ │ ② STORE │ │ ③ TRANSFORM│ │ SERVE │ │ │ │ CDC,stream,│ │ durable │ │ raw → clean│ │ SQL, BI, │ │ │ │ batch pull │ │ table fmt │ │ → modeled │ │ API, ML │ │ │ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │ │ │ │ ┌──────────────────── cross-cutting, span every stage ────────────────┐ │ │ │ ④ ORCHESTRATE schedule, depend, retry, backfill │ │ │ │ ⑤ SERVE warehouse / BI / feature store / NL-to-SQL │ │ │ │ ⑥ GOVERN catalog, lineage, access control, contracts, PII │ │ │ │ ⑦ OBSERVE freshness, volume, schema drift, cost, SLAs │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────┘

Read left to right, the first three are the data path: ingest moves bytes in, store holds them durably, transform turns raw landings into trustworthy models. The last four are cross-cutting: orchestration drives the path, serving exposes the output, governance keeps it legal and trustworthy, and observability tells you when it breaks. Later chapters take one slot each — ingest (04), store (05), modeling and transform (06–07), serving (08), governance (09–11), observability (10).

You are choosing how to fill slots, not which tool is "best"

The unproductive version of the stack debate is "Snowflake vs Databricks vs open source" as a religious war. The productive version: lay out the seven slots, and for each one decide buy a managed slot, operate an open one, or let one platform cover several at once. Stack B and C are bets that fewer, tightly-integrated slots beat best-of-breed; Stack A is the bet that composability and zero lock-in beat integration. Everything below is that bet, made concrete.

Stack A — Open-source lakehouse

The "own everything" stack. You assemble best-of-breed open components on object storage, run them yourself (on Kubernetes or managed equivalents), and pay almost nothing in license fees — trading that cash for engineering headcount. This is the stack large, infra-capable teams reach for, and it is the most natural home for GridDP's telemetry firehose because the time-series specialist (ClickHouse) is a first-class citizen rather than a bolt-on.

STACK A — OPEN-SOURCE LAKEHOUSE ──────────────────────────────────────────────────────────────────────────── SOURCES INGEST STORE TRANSFORM SERVE ───────── ────── ───── ───────── ───── Postgres ──CDC──▶ Debezium ─┐ ┌─ dbt-core ──┐ (mkt-api, + Flink │ │ on Spark │ billing) ├─▶ Kafka / ─▶ Iceberg ───┤ / Trino ├─▶ Trino │ Redpanda on S3 │ │ (BI/SQL) mkt-events ──────▶ Kafka ────┤ (the bus) (bronze/ └─ Trino SQL ─┘ │ (Kafka) │ silver/gold) ▼ │ Superset/ host-agent ⚡ ───▶ Kafka ────┘ Cube + BI TELEMETRY │ ~150 M/day └────────────▶ ClickHouse ──────────────▶ ops (time-series firehose) dashboards + ML feats ORCHESTRATE: Dagster (asset graph, backfills, sensors) GOVERN: Apache Polaris / Nessie (Iceberg catalog) + DataHub (lineage, PII) ML/FEATURES: Feast (feature store) + MLflow (tracking, registry) SEMANTIC: Cube / dbt MetricFlow │ NL-to-SQL: self-hosted LLM + Cube ────────────────────────────────────────────────────────────────────────────

How the slots are filled: ingest is Debezium for CDC and Flink for stream processing, all flowing through Kafka or Redpanda as the bus. Store is Apache Iceberg tables on S3 (the open table format that gives you ACID, time-travel, and schema evolution without a proprietary engine), with the firehose forked off to ClickHouse. Transform is dbt-core compiling SQL that runs on Spark or Trino. Orchestrate is Dagster. Govern is an Iceberg catalog (Polaris or Nessie) plus DataHub for lineage and PII tagging. ML is Feast plus MLflow.

ProsCons
No vendor lock-in. Iceberg on S3 is portable; any engine can read it.Highest engineering headcount. You operate Kafka, Flink, Trino, ClickHouse — each a system with on-call.
Lowest license cost. You pay for infrastructure, not seats or DBUs/credits.You operate everything. Upgrades, security patches, capacity, failover are all yours.
Composable. Swap any layer (Trino → DuckDB, Dagster → Airflow) without rewriting the rest.Integration burden. The "glue" between components — catalogs, schemas, auth — is unowned and is your job.
Best home for the firehose. ClickHouse for 150 M telemetry rows/day is the most cost-effective option of any stack.Slower time-to-value. Standing up a coherent platform takes months, not weeks.
Open-source is "free" the way a puppy is free

The license is $0; the total cost of ownership is several senior engineers' salaries. Stack A makes economic sense when you have (or are deliberately building) a platform team that would exist anyway, when lock-in is a board-level concern, or when your workload — like the telemetry firehose — is genuinely cheaper on specialized open infrastructure at your scale. We make this TCO argument rigorously in build vs buy.

Stack B — Databricks-centric

The "lakehouse, managed, ML-first" stack. Databricks gives you a single platform built on open Delta Lake, with Spark as the compute substrate for everything — batch, streaming, and ML. You still write code (notebooks, SQL, Python), but the cluster management, table format, catalog, and ML tooling are integrated and operated for you. This is the stack to pick when machine learning and large-scale Spark transformation are central to the product — which, for a marketplace computing DLPerf scores, reliability models, and dynamic pricing, they are.

STACK B — DATABRICKS-CENTRIC ──────────────────────────────────────────────────────────────────────────── SOURCES INGEST STORE TRANSFORM SERVE ───────── ────── ───── ───────── ───── Postgres ──CDC──▶ Debezium ─┐ ┌──────────────┐ ┌─ DLT / dbt ─┐ (mkt-api, /Kafka │ │ Delta Lake │ │ on Spark │ billing) ├─▶ Auto Loader ──────┼──▶│ (bronze/ ├─▶ Databricks │ + DLT │ │ silver/ │ SQL mkt-events ──────▶ Kafka ────┤ (Structured │ │ gold) │ (Photon) (Kafka) │ Streaming) │ └─────────────┘ │ │ │ Unity │ ▼ host-agent ⚡ ───▶ Kafka ────┘ │ Catalog │ Genie / AI-BI TELEMETRY ┌────────────┘ governs ALL │ dashboards ~150 M/day ▼ └──────────────┘ (firehose: Delta + Spark SS, or fork to ClickHouse — see §hybrid) ORCHESTRATE: Databricks Workflows GOVERN: Unity Catalog (one catalog for tables, files, models, lineage, ACLs) ML/FEATURES: Databricks Feature Store + MLflow + Mosaic (GenAI/training) SEMANTIC: Unity Catalog metrics / dbt │ NL-to-SQL: Databricks Genie ────────────────────────────────────────────────────────────────────────────

Slot fill: ingest is Auto Loader and Delta Live Tables on Structured Streaming (with Debezium upstream for CDC). Store is Delta Lake — open-format, ACID, with the bonus that it is the same format the ML training reads. Transform is DLT or dbt, both on Spark. Orchestrate is Databricks Workflows. Govern is Unity Catalog — the genuine differentiator: one catalog governing tables, files, ML models, and notebooks with unified lineage and access control. Serve is Databricks SQL with the Photon engine; NL-to-SQL is Genie. ML is the tightest of the three stacks: Feature Store, MLflow, and Mosaic all live where the data already is.

ProsCons
Best when ML + large Spark are central. No data movement between warehouse and ML platform — they are the same platform.Cost. DBUs on top of cloud compute add up; idle/oversized clusters are a classic budget leak.
Unified governance. Unity Catalog over tables, files, and models is hard to replicate in Stack A.Compute lock-in. Delta is open, but DLT, Photon, and the runtime are not — pipelines bind you to Databricks compute.
Strong lakehouse. One copy of data serves BI, streaming, and training; open Delta avoids storage lock-in.Less ideal as a pure SQL-analyst tool. Analyst ergonomics trail Snowflake; the platform is engineer-shaped.
Spark-native streaming handles the firehose in-platform if you accept the cost.Notebook sprawl & cluster ops still need governance discipline you must impose.

Stack C — Snowflake-centric

The "managed warehouse, analyst-first" stack. Snowflake separates storage from compute, manages essentially everything, and gives analysts the cleanest SQL experience of the three. You provision virtual warehouses (compute that spins up in seconds, scales independently, and auto-suspends), point connectors at your sources, and write SQL. It is the fastest path from zero to a working analytics platform — which is why it wins on time-to-value and is the default for analyst-heavy organizations.

STACK C — SNOWFLAKE-CENTRIC ──────────────────────────────────────────────────────────────────────────── SOURCES INGEST STORE TRANSFORM SERVE ───────── ────── ───── ───────── ───── Postgres ──────▶ Fivetran / ──┐ ┌────────────┐ ┌─ dbt Cloud ┐ (mkt-api, connectors │ │ Snowflake │ │ │ billing) ├──────▶ │ tables(FDN)├──┤ +Dynamic ├─▶ virtual │ │ + Iceberg │ │ Tables │ warehouses mkt-events ──────▶ Snowpipe ───┤ └────────────┘ └────────────┘ (BI/SQL) (Kafka) Streaming │ │ │ │ Snowpark for ▼ host-agent ⚡ ───▶ (awkward!) ─┘ Python/ML Cortex Analyst TELEMETRY → usually forks to ClickHouse; (NL → SQL) ~150 M/day native Snowflake is costly here — see §hybrid ORCHESTRATE: Snowflake Tasks (or Airflow) GOVERN: Snowflake Horizon (catalog, lineage, tagging, masking, access) ML/FEATURES: Snowflake Feature Store + Snowpark │ NL-to-SQL: Cortex Analyst SEMANTIC: Snowflake Semantic Views / dbt ────────────────────────────────────────────────────────────────────────────

Slot fill: ingest is Snowpipe Streaming for events and Fivetran-style managed connectors for OLTP and third-party APIs. Store is Snowflake's native tables (the FDN format) plus Iceberg for openness where you want it. Transform is dbt Cloud plus Dynamic Tables (declarative, incrementally-refreshed materializations — you declare the target SQL and a freshness target, Snowflake maintains it). Orchestrate is Tasks. Govern is Horizon. Serve is virtual warehouses; NL-to-SQL is Cortex Analyst, the most polished of the three. ML is Snowpark plus the Feature Store.

ProsCons
Fastest time-to-value. Connectors + SQL + a dashboard in days, not months.Cost at scale. Credit-based pricing is gentle early and punishing on large, frequent compute.
Best analyst ergonomics. The SQL surface, sharing, and zero-copy cloning are unmatched.Lock-in. Native FDN tables and the SQL dialect bind you; Iceberg helps but you give up some features.
Storage/compute separation. Scale and isolate workloads independently; auto-suspend kills idle cost.Telemetry firehose is awkward. 150 M time-series rows/day through warehouses is expensive and ill-fitting.
Managed. Near-zero ops; no clusters, no patching, no capacity planning.Heavy ML/Spark workloads fit less naturally than on Databricks.
The firehose is Stack C's structural weakness

Recall from Start Here that ~80% of GridDP's bytes are telemetry. A pure Snowflake stack handles the relational 80% of the questions beautifully and the firehose 80% of the bytes badly. Loading raw per-10-second samples into virtual warehouses and querying them with SQL works at 1,000 GPUs and detonates the credit bill at 17,000. This is not a Snowflake flaw — it is a column-store warehouse being asked to do a time-series engine's job. The fix is the same hybrid every stack converges on (next-but-one section).

The big side-by-side

Here is the head-to-head across the dimensions that actually decide the choice. Ratings are relative (★ = weak fit, ★★★★★ = best-in-class) for GridDP's profile — a mid-stage two-sided marketplace with a heavy telemetry firehose and a small-to-medium analyst/ML team.

DimensionStack A — OSS lakehouseStack B — DatabricksStack C — Snowflake
Cost modelInfra only; license ~$0. Cost = salaries.DBUs + cloud compute; pay per cluster-hour.Credits; pay per warehouse-second + storage.
Lock-in★ Lowest — Iceberg/Kafka are portable.★★★ Open storage (Delta), proprietary compute.★★★★ Highest — native format + dialect.
Ops burden / headcount★★★★★ Highest — you run everything.★★★ Managed runtime, but cluster & cost ops remain.★ Lowest — near-zero infra ops.
Time-to-value★ Months to a coherent platform.★★★ Weeks; ML path is quick.★★★★★ Days; fastest of the three.
Streaming maturity★★★★★ Flink/Kafka are the reference.★★★★ Structured Streaming / DLT are strong.★★★ Snowpipe Streaming + Dynamic Tables, improving.
ML / feature support★★★ Feast + MLflow, but you wire it up.★★★★★ Best — Feature Store, MLflow, Mosaic native.★★★ Snowpark + Feature Store, less Spark-native.
SQL-analyst UX★★ Trino/Superset workable, rough edges.★★★ Databricks SQL is solid, engineer-shaped.★★★★★ Best — the analyst gold standard.
Telemetry-firehose fit★★★★★ ClickHouse is first-class & cheap.★★★ Spark SS works; cost pushes you to ClickHouse.★★ Awkward & expensive; almost always forked out.
Governance★★★ Polaris/Nessie + DataHub, assembled.★★★★★ Unity Catalog over tables, files, models.★★★★ Horizon — strong, warehouse-centric.
NL-to-SQL / AI★★ Self-hosted LLM + Cube; DIY.★★★★ Genie / AI-BI, integrated.★★★★★ Cortex Analyst, most polished.
No row is "best overall"

Notice there is no column of all five-stars. A wins streaming, firehose-fit, and lock-in; B wins ML and governance; C wins time-to-value, analyst UX, and NL-to-SQL. The choice is a weighted sum where you supply the weights — and the weights come from your team and your workload, not from a benchmark. That is exactly what the decision framework formalizes next.

A decision framework

Reduce the comparison to a small number of questions answered in order. Each prunes the space; the first one that gives a confident answer usually settles it. Walk the tree top-down for GridDP and you can predict where it lands.

START: choose the MAIN business-data platform (firehose handled separately, see §hybrid) │ ├─ Q1. Is avoiding vendor lock-in a board-level / strategic mandate? │ └─ YES ─────────────────────────────────────────────▶ STACK A │ └─ no ─▼ │ ├─ Q2. Do you have (or will you fund) a 4+ engineer platform team? │ └─ NO ──────────────────────────────────────────────▶ STACK C (managed) │ └─ yes ─▼ │ ├─ Q3. Is large-scale ML / Spark CENTRAL to the product itself? │ │ (ranking models, fraud, dynamic pricing on the critical path) │ └─ YES ─────────────────────────────────────────────▶ STACK B │ └─ no ─▼ │ ├─ Q4. Is the primary consumer the SQL analyst & exec (vs the ML engineer)? │ └─ YES ─────────────────────────────────────────────▶ STACK C │ └─ no ─▼ │ ├─ Q5. What is the capital model — cash-rich & speed-hungry, or eng-rich & cost-sensitive? │ └─ speed/managed ────────────────────────────────────▶ STACK B or C │ └─ eng-rich/cost ────────────────────────────────────▶ STACK A │ └─ ALWAYS: carve the ~150 M-samples/day firehose into a time-series engine (ClickHouse), regardless of the answer above. → you are now running a HYBRID.

For GridDP specifically: lock-in is a concern but not an absolute mandate (Q1 → no); the company can fund a small platform team but it is not large (Q2 → marginal); ML is central — DLPerf, reliability, fraud, and dynamic pricing are product features, not back-office reports (Q3 → yes). That routes the business-data platform toward Stack B, with strong arguments for C on the analyst side — and, as the final ALWAYS rule states, the firehose is split out no matter what. In other words, the framework predicts a hybrid, which is exactly what real companies build.

Decide once, at the right altitude

The framework is intentionally coarse. Do not re-litigate the stack every quarter or per-pipeline — that is how you end up with three half-migrations and no platform. Decide the main platform once based on team and workload, accept that the firehose is a separate decision, and then spend your energy on the things that actually compound: models, contracts, and golden paths.

Why real companies run hybrids, not one pure stack

The reference stacks are pedagogical extremes. No mature company runs a religiously pure A, B, or C. They run a dominant main platform plus a small number of deliberate specialists — and at a telemetry-heavy company the most important specialist is forced on you by physics, not preference.

THE DOMINANT REAL-WORLD PATTERN (and what GridDP runs) ──────────────────────────────────────────────────────────────────────────── ┌──────────────────────────────────────┐ business data ──▶│ MAIN PLATFORM (Stack B or C) │──▶ analysts, finance, (OLTP, events, │ warehouse / lakehouse │ BI, NL-to-SQL, payments) │ relational models, joins, metrics │ most "questions" └──────────────────────────────────────┘ ▲ │ pre-aggregated rollups │ (per-GPU-hour, ~10 M/day) │ host-agent ⚡ ──▶┌──────────────────────────────────────┐──▶ ops dashboards, TELEMETRY │ SPECIALIST TS ENGINE (ClickHouse) │ reliability ML, ~150 M/day │ raw firehose, sub-second range scans │ fleet health └──────────────────────────────────────┘ ──────────────────────────────────────────────────────────────────────────── ~80% of BYTES live left in ClickHouse; ~80% of QUESTIONS answered on the right.

This is the same 80/20 asymmetry from Start Here, now expressed as architecture. The relational business data — accounts, rentals, bids, invoices, payments — is small, high-value, heavily joined, and the source of most questions; it belongs in the warehouse/lakehouse. The telemetry firehose is huge, time-series, and read with range-scan queries ("util for GPU X over window W"); it belongs in a column-oriented time-series engine. Only pre-aggregated rollups (per-GPU-hour) cross from the firehose into the main platform, where they join to billing and reliability. We design that boundary in detail in chapters 05 and 14.

The firehose forces a split — pick A/B/C for everything else

Whichever main stack you choose, the ~150 M-samples/day firehose pushes you toward a specialist time-series store. Even Stack B, which can process it natively in Spark Structured Streaming, usually forks it to ClickHouse on cost grounds; Stack C nearly always does. So reframe the decision: the A-vs-B-vs-C choice is really about the business-data platform, and the firehose is a near-orthogonal decision that lands on a time-series engine almost regardless. Treating them as one question is how teams over-spend on warehouse credits.

Build vs buy

Every slot you fill is a build-or-buy decision. Getting these right is most of what separates a platform that scales from one that drowns in maintenance. The rule of thumb: buy the commoditized, undifferentiated heavy lifting; build only the thin layer that encodes your company's specific knowledge.

CategoryExamplesVerdict & why
Never buildStorage/table engines, CDC machinery, query engines, schedulers' coreSolved, battle-tested, and a bottomless maintenance pit. Building your own Iceberg, Debezium, or Spark is how a data team accidentally becomes an infrastructure vendor with one customer.
Usually buy / adopt OSSCatalog, lineage, BI tool, feature store, orchestratorMature options exist (managed or open). Adopt; integrate; don't reinvent. Your value is in configuring them well, not authoring them.
Worth buildingSemantic-layer glue, internal CLIs / golden paths, contract & quality CI, the firehose↔warehouse rollup boundaryThis is the thin layer encoding your domains and conventions. No vendor knows that GridDP's revenue ties to the ledger or that telemetry gaps feed the reliability score. Building here compounds.

A concrete "worth building" example: a golden-path scaffold so any engineer creates a contract-checked, lineage-registered dataset with one command, instead of hand-wiring dbt, the catalog, and tests each time.

internal CLI — a golden path worth building (sketch)
# `griddp new-dataset` scaffolds the thin glue, not the engines
dataset: fleet.gpu_hourly_utilization
domain: supply            # → maps to catalog namespace + ACL group (ch. 11)
source: clickhouse.telemetry_sample
materialize:
  engine: dbt             # we BUY dbt; we BUILD the convention around it
  grain: gpu_id, hour
  freshness_sla: 30m      # → wired into the observability checks (ch. 10)
contract:
  owner: supply-ops
  pii: false
  tests: [not_null(gpu_id), accepted_range(util_pct, 0, 100)]
emits_rollup_to: warehouse.gold.fct_telemetry_hourly   # the firehose↔warehouse boundary
The TCO illusion of "free" open source

Stack A's license cost is zero, which fools people into reading it as the cheap option. It is not. At GridDP's scale the dominant line item in every stack is engineering salaries, and Stack A demands the most of them — you are paying senior engineers to operate Kafka, Trino, and ClickHouse instead of paying a vendor to operate the equivalent. The honest comparison is total cost of ownership: license + infrastructure + the fully-loaded cost of the people who keep it running. Sometimes Stack A still wins that math (you needed the platform team anyway, or your firehose is genuinely cheaper on ClickHouse). Often it does not. Run the TCO with salaries in it before you call open source "free."

Takeaway

  • Every data architecture fills the same seven capability slots — ingest, store, transform, orchestrate, serve, govern, observe. You are choosing how to fill them, not which tool is universally "best."
  • Stack A (OSS lakehouse) minimizes license cost and lock-in and is the best home for the firehose, at the price of the highest engineering headcount.
  • Stack B (Databricks) wins when ML and large-scale Spark are central, with the strongest unified governance — costlier and engineer-shaped.
  • Stack C (Snowflake) wins on time-to-value, analyst ergonomics, and NL-to-SQL — but the telemetry firehose is awkward and expensive on it.
  • No stack wins every dimension; the choice is a weighted sum, and a short decision tree (lock-in mandate? platform team? ML-central? analyst-first? capital model?) settles it.
  • Real companies — and GridDP — run hybrids: a main warehouse/lakehouse for business data plus a ClickHouse-style time-series engine carved out for the ~150 M-samples/day firehose. The firehose forces this split regardless of the main stack.
  • Never build storage engines or CDC; buy the commodity slots; build only the thin glue (semantic layer, golden paths, the firehose↔warehouse boundary) that encodes your domains. And remember the TCO illusion: "free" open source is paid for in salaries.

With the architecture chosen at the slot level, we descend into the first slot in earnest. → Ingestion & Pipelines — CDC, streaming, and batch, applied to all nine sources.