<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Dataglot - Blog</title>
      <link>https://dataglot.ai/blog/</link>
      <description>Rust-native federated SQL query engine with governance enforced in the query plan.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://dataglot.ai/blog/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sun, 23 Aug 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Introducing Dataglot</title>
          <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://dataglot.ai/blog/introducing-dataglot/</link>
          <guid>https://dataglot.ai/blog/introducing-dataglot/</guid>
          <description xml:base="https://dataglot.ai/blog/introducing-dataglot/">&lt;p&gt;Today we&#39;re launching &lt;a rel=&quot;external&quot; href=&quot;https://github.com/dataglotai/dataglot&quot;&gt;Dataglot&lt;/a&gt;: a Rust-native federated SQL query engine with governance enforcement compiled into the query plan. It speaks the PostgreSQL wire protocol, so &lt;code&gt;psql&lt;/code&gt;, DBeaver, Metabase, Tableau, dbt, and every Postgres driver you already use connect with no special client. You point it at the databases you already run — PostgreSQL, MySQL, Oracle, Snowflake, S3/Parquet, Apache Iceberg — and query across all of them in one SQL statement, with column masks and row filters that are structurally guaranteed, not bolted on.&lt;/p&gt;
&lt;p&gt;It&#39;s Apache-2.0 licensed, and you can run your first governed, cross-source query in about five minutes with nothing but Docker.&lt;/p&gt;
&lt;h2 id=&quot;why-we-built-it&quot;&gt;Why we built it&lt;/h2&gt;
&lt;p&gt;Dataglot exists because regulated enterprises — banks, insurers, healthcare systems — have two problems that current tooling doesn&#39;t solve together.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Governance definitions don&#39;t translate to enforcement.&lt;/strong&gt; Nearly every regulated organization runs a governance platform: DataHub, Informatica, Collibra, Alation. The vendor varies, but the shape is constant — a catalog of datasets, columns, classifications, and policies. That catalog is the &lt;em&gt;definition&lt;/em&gt; of how data should be treated. The gap is enforcement. A steward classifies a column as PII, and nothing in the query engine structurally guarantees that column is never returned in plaintext to the wrong user. Enforcement today is post-parse SQL rewrites injected in front of the engine (fragile), UDFs deployed to every worker (invisible to consumers), access-request ticketing (human-in-the-loop, not structural), or &quot;we trust the BI tool&quot; (not enforcement at all). Auditors know this. Regulators know this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The economics of proprietary analytical appliances are punishing.&lt;/strong&gt; The workloads those policies apply to often run on hardware appliances locked into multi-year refresh cycles, where a single box can represent an eight-figure commitment over the contract term. Organizations want an exit path that doesn&#39;t require rewriting every query, re-platforming every dashboard, and abandoning the governance investment they already made.&lt;/p&gt;
&lt;p&gt;One engine can address both: federate the existing data estate through a single PostgreSQL-compatible endpoint, and make the governance platform&#39;s definitions a query-time guarantee inside that engine. Your governance platform defines what PII means in your organization; Dataglot is where that definition becomes enforceable.&lt;/p&gt;
&lt;h2 id=&quot;what-governance-in-the-plan-means&quot;&gt;What &quot;governance in the plan&quot; means&lt;/h2&gt;
&lt;p&gt;Most policy enforcement rewrites SQL text after parsing, or filters rows after execution. Dataglot compiles policy into the physical query plan itself. Masks and row filters become typed expression predicates pushed into the scan — which means a masked column is &lt;strong&gt;never fetched from storage&lt;/strong&gt;, on any code path, for any client. There is no execution path that returns ungoverned data, because the engine never retrieved it.&lt;/p&gt;
&lt;p&gt;The guarantee is also &lt;em&gt;visible&lt;/em&gt;. &lt;code&gt;EXPLAIN&lt;/code&gt; shows the policy-enforcement pass in the plan, and &lt;code&gt;EXPLAIN FEDERATION&lt;/code&gt; shows exactly what SQL was shipped to each source — whole aggregations, not just scans.&lt;/p&gt;
&lt;h2 id=&quot;what-works-today&quot;&gt;What works today&lt;/h2&gt;
&lt;p&gt;Dataglot is pre-1.0 and moving fast, but the current release (v0.5.0) is already a substantial engine. As of today it ships:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Federation&lt;/strong&gt; across PostgreSQL, MySQL, Oracle, Snowflake, object storage (S3/Parquet), and Apache Iceberg, plus a generic ADBC bring-your-own-driver connector — with cost-aware pushdown and &lt;code&gt;EXPLAIN FEDERATION&lt;/code&gt; to prove it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plan-time governance&lt;/strong&gt;: named mask types (redact, hash, show-first/last-N, nullify, and more), row filters, table- and column-level access deny, role resolution, and lineage-propagated masking — a mask on a source column automatically covers every derived column that descends from it. Masks apply inside subqueries too; we test the bypass paths.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A SQL-native control plane.&lt;/strong&gt; A running server is administered entirely over the pg wire: &lt;code&gt;CREATE CATALOG&lt;/code&gt;, &lt;code&gt;CREATE SECRET&lt;/code&gt; (encrypted at rest), &lt;code&gt;CREATE USER&lt;/code&gt;/&lt;code&gt;ROLE&lt;/code&gt;, &lt;code&gt;GRANT&lt;/code&gt;/&lt;code&gt;REVOKE&lt;/code&gt;, &lt;code&gt;CREATE MASK&lt;/code&gt;, &lt;code&gt;CREATE ROW FILTER&lt;/code&gt;, &lt;code&gt;CREATE VIEW&lt;/code&gt;. No config edit, no restart.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise authentication&lt;/strong&gt;: SCRAM-SHA-256 and md5, LDAP/Active Directory group resolution, pg-wire ingress TLS, TLS to source databases, and connection admission control with per-identity rate ceilings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Governance integrations&lt;/strong&gt;: column-level OpenLineage events on every query, DataHub data-product registration, policy explainability (&lt;code&gt;POST /policy/explain&lt;/code&gt; tells you why a row was excluded or a column masked), and an inbound webhook so tag changes in your governance platform propagate to enforcement in under a minute.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distributed execution&lt;/strong&gt; on Apache Ballista with object-store-based scheduler HA (no ZooKeeper, no etcd), cluster mTLS, and near-linear scaling measured on TPC-H across four workers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operations&lt;/strong&gt;: a live dashboard (source health, query history, sessions, governance posture), a structured audit event for every policy decision, emitted on a dedicated &lt;code&gt;dataglot::audit&lt;/code&gt; log target for your collector, and a multi-engine browser testbench that diffs Dataglot&#39;s results row-by-row against other engines.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And a hard constraint we&#39;ve held from day one: &lt;strong&gt;no JVM in the production runtime&lt;/strong&gt;. Dataglot is a single Rust binary, built on the proven Apache DataFusion and Arrow foundation.&lt;/p&gt;
&lt;h2 id=&quot;honest-scope&quot;&gt;Honest scope&lt;/h2&gt;
&lt;p&gt;Dataglot is a read-path federation and governance engine. It is not a general-purpose PostgreSQL replacement, and it&#39;s not trying to be a SaaS data-integration tool — &lt;a href=&quot;/blog/what-we-build-and-what-we-wont/&quot;&gt;we wrote about that boundary separately&lt;/a&gt;. The &lt;a href=&quot;/docs/compatibility/&quot;&gt;client compatibility matrix&lt;/a&gt; documents exactly which tools work and where the edges are.&lt;/p&gt;
&lt;h2 id=&quot;try-it-in-five-minutes&quot;&gt;Try it in five minutes&lt;/h2&gt;
&lt;p&gt;No build step, no toolchain — grab a prebuilt Dataglot and go:&lt;/p&gt;
&lt;div class=&quot;code-tabs&quot; data-labels=&quot;Docker, Homebrew&quot;&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #59C2FF;&quot;&gt;docker&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; pull ghcr.io/dataglotai/dataglot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #59C2FF;&quot;&gt;brew&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; install dataglotai/tap/dataglot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Point it at a database you already have, connect with plain &lt;code&gt;psql&lt;/code&gt;, and run a governed query:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #59C2FF;&quot;&gt;psql&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; &amp;quot;host=localhost port=5432 user=demo dbname=demo&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; u&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;email&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;o&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;FROM&lt;/span&gt;&lt;span&gt;   users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;   pg_orders&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;public&lt;/span&gt;&lt;span&gt;.orders o &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; u&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt; o&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span style=&quot;color: #95E6CB;&quot;&gt;user_id&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&#39;ll see the cross-source join work — and &lt;code&gt;email&lt;/code&gt; come back masked, because the policy was compiled into the plan before a single row moved.&lt;/p&gt;
&lt;p&gt;Each &lt;a rel=&quot;external&quot; href=&quot;https://github.com/dataglotai/dataglot/releases&quot;&gt;GitHub release&lt;/a&gt; also ships Linux and macOS tarballs with checksums. The &lt;a href=&quot;/docs/getting-started/&quot;&gt;quickstart&lt;/a&gt; walks through connecting your first sources and writing your first mask, end to end.&lt;/p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#39;s next&lt;/h2&gt;
&lt;p&gt;Near-term work concentrates on connector depth for the sources regulated workloads actually run on, richer governance-platform integrations, and hardening the distributed write path (materializations, compaction, ingestion) on &lt;code&gt;iceberg-rust&lt;/code&gt;. The &lt;a rel=&quot;external&quot; href=&quot;https://github.com/dataglotai/dataglot/blob/main/CHANGELOG.md&quot;&gt;changelog&lt;/a&gt; is the honest record — every release documents what landed and what broke.&lt;/p&gt;
&lt;p&gt;If plan-time governance over your existing databases sounds like the missing piece in your stack, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/dataglotai/dataglot&quot;&gt;star the repo&lt;/a&gt;, run the &lt;a href=&quot;/docs/getting-started/&quot;&gt;quickstart&lt;/a&gt;, and tell us what breaks. We&#39;re building this in the open.&lt;/p&gt;
</description>
      </item>
      <item>
          <title>The One Line That Cannot Move</title>
          <pubDate>Thu, 20 Aug 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://dataglot.ai/blog/the-line-that-cannot-move/</link>
          <guid>https://dataglot.ai/blog/the-line-that-cannot-move/</guid>
          <description xml:base="https://dataglot.ai/blog/the-line-that-cannot-move/">&lt;p&gt;Every data governance program has the same load-bearing sentence somewhere in its documentation: &lt;em&gt;&quot;columns classified as PII are masked for unauthorized users.&quot;&lt;/em&gt; The classification half of that sentence is a solved problem — DataHub, Informatica, Collibra and their peers are genuinely good at capturing what PII means in your organization, who owns it, and what policy should apply to it.&lt;/p&gt;
&lt;p&gt;The enforcement half is where the sentence quietly becomes fiction. This post is about why, and about the design decision at the center of Dataglot: &lt;strong&gt;policy is compiled into the physical query plan, and that is the one line in the architecture that cannot move.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-enforcement-actually-works-today&quot;&gt;How enforcement actually works today&lt;/h2&gt;
&lt;p&gt;Walk into any regulated enterprise and ask how a PII tag becomes runtime behavior. You&#39;ll find some combination of four mechanisms:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Post-parse SQL rewrites.&lt;/strong&gt; A policy agent intercepts the query after parsing and injects &lt;code&gt;WHERE&lt;/code&gt; clauses or wraps columns in masking expressions — as SQL strings. This is enforcement by string manipulation. It has to correctly handle every dialect corner, every subquery shape, every view expansion, every CTE. Miss one and the data walks out. The rewrite is also invisible in the plan: an auditor can&#39;t point at the artifact that proves the mask was applied, only at the config that says it should have been.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UDF-based filtering.&lt;/strong&gt; Row filters implemented as user-defined functions — &lt;code&gt;current_user()&lt;/code&gt; checks, group-membership lookups — deployed to every worker in the cluster. UDFs must be kept in sync across the fleet, they&#39;re opaque to the optimizer (so they&#39;re also slow), and they&#39;re invisible to consumers of the data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ticketing workflows.&lt;/strong&gt; Access requests approved by humans. Valuable as process, but a human-in-the-loop workflow is not a structural control; it&#39;s a record that someone intended one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;The BI tool handles it.&quot;&lt;/strong&gt; Column-level security configured in the dashboard layer, while every other client — the notebook, the cron job, the AI agent with a database credential — talks to the engine directly.&lt;/p&gt;
&lt;p&gt;Auditors know all of this. It&#39;s why evidence-gathering for a data-access audit is an archaeology project rather than a query.&lt;/p&gt;
&lt;h2 id=&quot;enforcement-at-plan-time&quot;&gt;Enforcement at plan time&lt;/h2&gt;
&lt;p&gt;Dataglot takes a different position. When a query is planned, the session context carries the caller&#39;s identity and group memberships. Policies attached to typed tags — &lt;code&gt;pii.email&lt;/code&gt;, &lt;code&gt;phi.diagnosis&lt;/code&gt;, whatever your taxonomy says — are resolved at that moment and become &lt;strong&gt;typed expression predicates compiled into the physical scan plan&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Two properties fall out of this that no rewrite-based system can offer:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Masked columns are never fetched.&lt;/strong&gt; The mask isn&#39;t applied to the result set; it replaces the column expression inside the scan itself. If your mask says an analyst sees &lt;code&gt;***@example.com&lt;/code&gt;, the engine never retrieves the plaintext from storage on that code path. There is no window between &quot;data read&quot; and &quot;mask applied,&quot; because there is no such sequence.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The guarantee is inspectable before execution.&lt;/strong&gt; The enforcement pass is a plan node. Run &lt;code&gt;EXPLAIN&lt;/code&gt; and you can see it:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;EXPLAIN &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;SELECT&lt;/span&gt;&lt;span&gt; email &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; users;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;-- ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;-- DataglotPolicyEnforcer: mask(email) pushed into scan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That plan is the audit artifact. Dataglot also exposes it as an API — &lt;code&gt;POST /policy/explain&lt;/code&gt; plans a query without executing it and reports exactly which masks, row filters, and deny rules would apply for any identity. &quot;Why was this row excluded?&quot; stops being a forensic question.&lt;/p&gt;
&lt;h2 id=&quot;structural-means-the-edge-cases-are-covered-by-construction&quot;&gt;Structural means the edge cases are covered by construction&lt;/h2&gt;
&lt;p&gt;The difference between structural and best-effort shows up in the unglamorous cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Subqueries.&lt;/strong&gt; A mask that applies to &lt;code&gt;SELECT email FROM users&lt;/code&gt; must equally apply when the same column is reached through an expression subquery three levels deep. In Dataglot it does, because enforcement operates on the plan — where all of those shapes have already been normalized — not on the SQL text.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Derived data.&lt;/strong&gt; A masked source column should stay masked in everything computed from it. Dataglot&#39;s column-level lineage analysis propagates masks along the lineage graph: a policy on &lt;code&gt;users.email&lt;/code&gt; automatically covers derived columns that descend from it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federation.&lt;/strong&gt; Policies ride along on cross-source joins. When &lt;code&gt;users&lt;/code&gt; lives in one Postgres and &lt;code&gt;orders&lt;/code&gt; in another, the plan that federates them carries the same enforcement nodes as a single-source query.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Every client, every protocol.&lt;/strong&gt; Because enforcement is in the plan, it&#39;s identical for &lt;code&gt;psql&lt;/code&gt;, a JDBC connection, a dbt run, and an AI agent. There is no privileged path around it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-partnership-this-implies&quot;&gt;The partnership this implies&lt;/h2&gt;
&lt;p&gt;None of this replaces your governance platform — it&#39;s the missing half of it. The division of authority is deliberate: the governance platform is the system of record for classifications, glossary terms, and stewardship decisions; Dataglot is the execution layer where those decisions become behavior. Tag a column as PII in DataHub, and the inbound policy webhook applies the corresponding enforcement in Dataglot within a minute. Every query then emits column-level OpenLineage back, so the catalog stays current with what&#39;s actually running.&lt;/p&gt;
&lt;p&gt;DataHub defines what PII means in your organization. Dataglot is where that definition becomes a query-time guarantee.&lt;/p&gt;
&lt;p&gt;That&#39;s the whole thesis. Everything else in the engine — federation, the SQL-native control plane, distributed execution — exists to make that guarantee available over the data estate you already have, without moving the data or rewriting the workloads.&lt;/p&gt;
&lt;h2 id=&quot;try-the-gap-demo-yourself&quot;&gt;Try the gap demo yourself&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;/docs/getting-started/&quot;&gt;five-minute demo&lt;/a&gt; ships with a masking and row-filter policy on &lt;code&gt;users.email&lt;/code&gt;. Run the same &lt;code&gt;SELECT&lt;/code&gt; as a governed identity and watch the plan do the work:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;SELECT&lt;/span&gt;&lt;span&gt; id, email &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;FROM&lt;/span&gt;&lt;span&gt; users &lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt;ORDER BY&lt;/span&gt;&lt;span&gt; id;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; id |      email&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5A6673;font-style: italic;&quot;&gt;----+-----------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;  2&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span style=&quot;color: #F29668;&quot;&gt;***&lt;/span&gt;&lt;span&gt;@example.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D2A6FF;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #FF8F40;&quot;&gt; row&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three users exist in the source. A governed session sees one, masked — and &lt;code&gt;EXPLAIN&lt;/code&gt; will show you exactly why.&lt;/p&gt;
</description>
      </item>
      <item>
          <title>What We Build — and What We Won&#39;t</title>
          <pubDate>Mon, 17 Aug 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://dataglot.ai/blog/what-we-build-and-what-we-wont/</link>
          <guid>https://dataglot.ai/blog/what-we-build-and-what-we-wont/</guid>
          <description xml:base="https://dataglot.ai/blog/what-we-build-and-what-we-wont/">&lt;p&gt;Every federated query engine eventually gets the same question: &lt;em&gt;&quot;do you have a connector for X?&quot;&lt;/em&gt; Answered case-by-case, that question turns your roadmap into a popularity contest. So we wrote down the rule, and this post is the public version of it.&lt;/p&gt;
&lt;p&gt;Our position in one paragraph:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dataglot is the federated SQL engine for regulated enterprises. We support the data sources your regulated workloads actually run on — Oracle, SQL Server, Db2, Teradata, HANA, Postgres, MySQL, Snowflake, Iceberg — plus the enterprise SaaS systems that hold related auditable data (SAP, ServiceNow, Workday). We are &lt;strong&gt;not&lt;/strong&gt; a SaaS data-integration tool — those exist and are excellent (Airbyte, Fivetran, Hightouch). We are the governance-enforcing query layer above them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-decision-rule&quot;&gt;The decision rule&lt;/h2&gt;
&lt;p&gt;Connector architecture in Dataglot is dictated by the source, not by preference:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If the source has a SQL engine and we want it to do work on our behalf&lt;/strong&gt;, we build a SQL-pushdown connector: Dataglot translates plan fragments back into the source&#39;s own SQL dialect, and the source executes them natively.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If the source&#39;s native query interface is not SQL&lt;/strong&gt; — REST, OData, key-value, document DSL — we build a native table adapter and translate typed filters into whatever the API accepts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why the distinction matters is pushdown. A table adapter can push projection, filters, and limits. A SQL-pushdown connector additionally pushes &lt;strong&gt;aggregations, same-source joins, &lt;code&gt;ORDER BY&lt;/code&gt;, &lt;code&gt;DISTINCT&lt;/code&gt;, subqueries, and window functions&lt;/strong&gt; to the source. For an aggregation over a terabyte-scale fact table on a database the customer already paid for, that&#39;s the difference between shipping one &lt;code&gt;GROUP BY&lt;/code&gt; query and getting a small answer back, versus pulling every row across the wire. Orders of magnitude in network bytes — and you can verify it, because &lt;code&gt;EXPLAIN FEDERATION&lt;/code&gt; shows the exact SQL shipped to each source.&lt;/p&gt;
&lt;p&gt;That&#39;s also why the sources we go deep on are the enterprise SQL engines. They&#39;re precisely the systems where pushdown pays: the source is very good at its own data, and Dataglot&#39;s job is to route the work there and enforce policy on what comes back.&lt;/p&gt;
&lt;h2 id=&quot;why-we-won-t-chase-connector-count&quot;&gt;Why we won&#39;t chase connector count&lt;/h2&gt;
&lt;p&gt;We could spend the next two years building SaaS connectors. We won&#39;t, for four structural reasons:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Engineering cost with no compounding.&lt;/strong&gt; Each SaaS connector is one to two weeks of bespoke OAuth, rate limits, pagination, and schema-discovery quirks. Fifty of them is more than an engineer-year that ships zero improvement to federation, governance, or the connectors regulated workloads depend on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No pushdown moat.&lt;/strong&gt; SaaS APIs have weak filter capability, so most of the query work happens in the engine anyway. The federation story — &quot;the source does the heavy lifting&quot; — simply doesn&#39;t apply when the bottleneck is a paginated REST API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Governance doesn&#39;t differentiate there.&lt;/strong&gt; Regulated-industry sensitive data does not, for the most part, live in Slack, Notion, or Jira. Plan-time masking of a project-management tool is a demo, not a compliance program.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The breadth race already has winners.&lt;/strong&gt; Airbyte has hundreds of connectors; Fivetran has more. Nobody pays a premium for the 87th connector. They pay for the one connector that solves their hard problem.&lt;/p&gt;
&lt;p&gt;So when someone asks whether Dataglot supports Slack or HubSpot, the honest answer is: Airbyte and Fivetran do that excellently — land the data in your warehouse or lakehouse, and Dataglot will govern and federate it from there. That&#39;s not a dodge; it&#39;s the architecture working as intended. Ingestion tools move data; Dataglot is the governed query layer above wherever the data lands.&lt;/p&gt;
&lt;h2 id=&quot;the-narrow-saas-slice-that-earns-its-seat&quot;&gt;The narrow SaaS slice that earns its seat&lt;/h2&gt;
&lt;p&gt;There is a small set of SaaS systems that genuinely belong in a regulated-enterprise data fabric, because they hold auditable, regulated, or compliance-relevant records:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SAP S/4HANA&lt;/strong&gt; — ERP and financial transactions, reachable over OData.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ServiceNow&lt;/strong&gt; — IT change management, the evidence trail for SOX-style controls.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workday&lt;/strong&gt; — HR and payroll data, regulated under GDPR/HIPAA for many enterprises.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Salesforce and Microsoft Dataverse&lt;/strong&gt; — selectively, where CRM records carry customer PII that policies must cover.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even here we resist bespoke crates. These sources speak OData or a REST-with-filters dialect, so they&#39;re built on a shared pair of adapters — one for OData, one for REST — and added as &lt;em&gt;configuration&lt;/em&gt;, not as new connector codebases. One well-designed adapter, many sources behind it.&lt;/p&gt;
&lt;h2 id=&quot;the-escape-hatch-bring-your-own-adbc-driver&quot;&gt;The escape hatch: bring your own ADBC driver&lt;/h2&gt;
&lt;p&gt;For the long tail, Dataglot ships a generic &lt;a rel=&quot;external&quot; href=&quot;https://arrow.apache.org/adbc/&quot;&gt;ADBC&lt;/a&gt; connector: point a catalog at any ADBC driver shared library, declare its SQL dialect from the whitelist the engine ships (&lt;code&gt;postgresql&lt;/code&gt;, &lt;code&gt;mysql&lt;/code&gt;, &lt;code&gt;sqlite&lt;/code&gt;, &lt;code&gt;duckdb&lt;/code&gt;, &lt;code&gt;bigquery&lt;/code&gt;), and you get full federation pushdown through your own driver — the generic-JDBC idea, minus the JVM.&lt;/p&gt;
&lt;p&gt;The contract is deliberately sharp: if your source speaks one of the shipped dialects, yes; otherwise, no. We don&#39;t do approximate dialect mappings that generate subtly wrong SQL against your data. When a source lacks a shipped dialect, the fix is landing that dialect upstream in &lt;a rel=&quot;external&quot; href=&quot;https://datafusion.apache.org/&quot;&gt;Apache DataFusion&lt;/a&gt;, the open engine foundation Dataglot builds on — which benefits everyone, not just us.&lt;/p&gt;
&lt;h2 id=&quot;the-discipline&quot;&gt;The discipline&lt;/h2&gt;
&lt;p&gt;A connector roadmap is a statement about what you believe your product is. Ours says: Dataglot wins by being &lt;em&gt;deep&lt;/em&gt; where regulated data lives — pushdown you can inspect, policy compiled into the plan, dialects handled correctly — and by composing cleanly with the excellent ingestion tools that already won breadth. Every engineering week spent on connector number 51 is a week not spent making Oracle pushdown better or closing a governance edge case. We know which of those our users are actually betting on.&lt;/p&gt;
&lt;p&gt;If you have a source you think clears the bar, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/dataglotai/dataglot/issues&quot;&gt;open an issue&lt;/a&gt; — the bar is written down, so the conversation is short either way.&lt;/p&gt;
</description>
      </item>
      <item>
          <title>The Evolution of Data Architecture</title>
          <pubDate>Sun, 16 Aug 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://dataglot.ai/blog/the-evolution-of-data-architecture/</link>
          <guid>https://dataglot.ai/blog/the-evolution-of-data-architecture/</guid>
          <description xml:base="https://dataglot.ai/blog/the-evolution-of-data-architecture/">&lt;p&gt;Every architectural decision Dataglot makes is a choice in a fifty-year argument. This essay explains the argument.&lt;/p&gt;
&lt;p&gt;The modern data stack didn&#39;t appear from thin air. It is the cumulative answer to fifty years of mismatch between the questions people ask and the systems they had to ask them with. The relational database in 1970, the warehouse in 1994, the data lake in 2006, Snowflake in 2014, Iceberg in 2017, Arrow standardizing in-memory in 2016 — each was a response to a specific failure of the era before it.&lt;/p&gt;
&lt;p&gt;The point is not to teach history for its own sake. It is that when someone says &quot;let&#39;s just keep the cache layer simple,&quot; everyone in the room should understand what that simplifies &lt;em&gt;away&lt;/em&gt;, what is lost by simplifying it, and which previous era&#39;s mistake would be repeated. Each chapter is a self-contained argument; read in order, they build the full mental model.&lt;/p&gt;
&lt;p&gt;The story begins with the bundled relational database, the moment analytics broke it, the column-store answer, and the moment the internet broke &lt;em&gt;that&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;chapter-1-the-original-bargain-1970s&quot;&gt;Chapter 1 — The original bargain (1970s)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/monolith-database.svg&quot; alt=&quot;One database box bundling catalog, compute, and storage — the original monolith&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One process, one machine, one set of tables. Catalog, compute, and storage bundled together. The ACID contract was easy because everything happened in the same place at the same time.&lt;/p&gt;
&lt;p&gt;The relational database, as Edgar Codd described it in 1970 and as IBM&#39;s System R and Berkeley&#39;s Ingres prototyped in the mid-1970s, was a complete world. The tables, the query engine, the transaction log, the indexes, and the access controls all lived inside a single trusted process running on a single machine. When a row was updated, the same process that knew about the table also wrote the change, also flushed the log, and also updated the index. There was no network boundary between any of these things, so there was nothing to coordinate, nothing to fail partway through, nothing to second-guess.&lt;/p&gt;
&lt;p&gt;This is what made the ACID contract — atomicity, consistency, isolation, durability — feel almost trivial in the early systems. Atomicity (&quot;all or nothing&quot;) is straightforward when there&#39;s only one writer. Consistency is straightforward when one process owns the schema. Isolation is straightforward when transactions are interleaved by a local lock manager. Durability is straightforward when the same process that holds the lock also fsyncs the log. The hard parts of ACID — distributed consensus, network partitions, partial failures — simply did not exist in the design space yet.&lt;/p&gt;
&lt;h3 id=&quot;storage-was-tuned-for-the-dominant-workload&quot;&gt;Storage was tuned for the dominant workload&lt;/h3&gt;
&lt;p&gt;The dominant workload was operational. Banks needed account balances. Airlines needed seat reservations. Retailers needed inventory levels. These were transactional questions: &quot;show me row 12,847,&quot; &quot;decrement quantity by one,&quot; &quot;insert this transaction.&quot; The database engineers therefore tuned storage for that workload. Rows were laid out on disk together — all the columns of one record in one place. B-tree indexes made it cheap to find a row by primary key. The whole machine was an answer to &quot;where is record N, and how do I update it safely?&quot;&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1970&lt;/td&gt;&lt;td&gt;Edgar Codd publishes &quot;A Relational Model of Data for Large Shared Data Banks&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1974–79&lt;/td&gt;&lt;td&gt;System R (IBM Research) implements the first SQL prototype&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1977&lt;/td&gt;&lt;td&gt;Oracle V2 ships — the first commercial relational database&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1979&lt;/td&gt;&lt;td&gt;Ingres ships out of Berkeley&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1980s&lt;/td&gt;&lt;td&gt;Sybase, Informix, DB2, Microsoft SQL Server&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;It is worth pausing on the shape of this system. Catalog, compute, and storage will reappear as separate, swappable layers in every architecture from the 2010s onward. In 1970, they are one rectangle. The history of the next fifty years is the story of that rectangle being pulled apart.&lt;/p&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Row storage and indexes optimize for one row at a time. This is OLTP — and it&#39;s the right shape when the question is operational. The bundling itself was never the problem.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The bundled architecture worked because it matched the workload. Operational systems still look like this today — Postgres, MySQL, the embedded SQLite in your phone. The problem appeared when people started asking a different shape of question.&lt;/p&gt;
&lt;h2 id=&quot;chapter-2-then-someone-asked-a-different-question&quot;&gt;Chapter 2 — Then someone asked a different question&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/row-vs-column.svg&quot; alt=&quot;Why row-oriented layout is expensive for analytics: a query touching two columns still reads every row&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&quot;Total revenue by region last quarter&quot; needs only two columns out of forty. But row storage forces the database to read every full row from disk. The wasted I/O is the architecture, not a bug.&lt;/p&gt;
&lt;p&gt;Sometime in the late 1980s and through the 1990s, businesses noticed that the same database that was running operations could in principle answer broader questions. Total revenue. Average order size. Trends across regions and quarters. These were not transactional questions about one row — they were aggregate questions over millions of rows.&lt;/p&gt;
&lt;p&gt;When you tried to run them on the operational database, two things happened. First, the queries were unbearably slow. Second, while they ran, the operational workload slowed down too, because the analytics queries were holding shared resources and saturating the disks. The architecture that was perfect for &quot;where is record N&quot; turned out to be terrible for &quot;summarize records 1 through N million.&quot;&lt;/p&gt;
&lt;h3 id=&quot;the-fundamental-cost-of-the-row-layout&quot;&gt;The fundamental cost of the row layout&lt;/h3&gt;
&lt;p&gt;On a row store, every record is laid out on disk as a contiguous block of all its columns. To compute &quot;total revenue by region,&quot; the database has to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read each row of the orders table off disk, in full&lt;/li&gt;
&lt;li&gt;Throw away thirty-eight of the forty columns&lt;/li&gt;
&lt;li&gt;Keep the two columns that the query actually needs&lt;/li&gt;
&lt;li&gt;Repeat ten million times&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The wasted I/O is not five percent or ten percent. For a forty-column table where two columns matter, the database is reading twenty times more bytes than it needs. Engineers called this &lt;strong&gt;read amplification&lt;/strong&gt; — and it was the architecture, not a bug to be fixed.&lt;/p&gt;
&lt;p&gt;It&#39;s tempting to suggest fixing this with indexes: just create an index on every column that gets queried. But indexes are not free. Every insert and every update has to rewrite every index that touches the changed columns. On a heavily-written operational table, indexing every analytical column kills write performance — which is the exact thing the operational database existed to do well. The architecture cannot serve both shapes of question.&lt;/p&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Analytical questions and operational questions are different shapes. Trying to answer both with the same data layout makes both slower than they need to be.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This was the moment when the field forked. Operational systems would keep their row stores, B-trees, and tight transactions. A second species of system would emerge — purpose-built for analytics, with a different storage layout, a different query model, and a different posture toward data.&lt;/p&gt;
&lt;h2 id=&quot;chapter-3-the-pioneers-turned-the-table-ninety-degrees-1994&quot;&gt;Chapter 3 — The pioneers turned the table ninety degrees (1994)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/warehouse-three-ideas.svg&quot; alt=&quot;The warehouse&amp;#39;s three ideas working together: columnar storage, star schemas, and parallel scan&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Sybase IQ shipped the first commercially-available column store in 1994. The trick was to lay out data column by column on disk. Reading two columns out of forty became cheap.&lt;/p&gt;
&lt;p&gt;Instead of each row being a contiguous block of all its columns, each &lt;em&gt;column&lt;/em&gt; was stored as a contiguous block of all its values. To answer &quot;total revenue by region,&quot; the database now read only the bytes for the two relevant columns. Thirty-eight other columns stayed where they were on disk. Read amplification disappeared.&lt;/p&gt;
&lt;p&gt;Sybase IQ was not the first columnar idea — academic systems and earlier work at Lockheed had explored it — but it was the first to ship as a productized, supported analytical database. The columnar idea later spread through MonetDB (1998, academic), C-Store (2005, the Stonebraker paper that became Vertica), and eventually into every modern analytical engine.&lt;/p&gt;
&lt;h3 id=&quot;three-ideas-not-just-one&quot;&gt;Three ideas, not just one&lt;/h3&gt;
&lt;p&gt;The data warehouse era introduced three distinct ideas, all of which still matter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Columnar storage&lt;/strong&gt; — the layout itself, optimized for scans. Cheap to read few columns; cheap to compress within a column because all values share a type.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MPP execution&lt;/strong&gt; — massively parallel processing: partition the data across many machines, run the query in parallel, combine results. Teradata had been doing this since the early 1980s; the warehouse era productized it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schema and modeling discipline&lt;/strong&gt; — Ralph Kimball&#39;s dimensional modeling and Bill Inmon&#39;s normalized warehouse both became standard practice. The warehouse demanded that data be cleaned, conformed, and modeled before it was loaded.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last point is what gave rise to the ETL industry. Data could not just appear in the warehouse — it had to be extracted from operational systems, transformed into the warehouse&#39;s schema, and loaded on a schedule. Tools like Informatica, DataStage, and Ab Initio were built specifically to run this nightly choreography.&lt;/p&gt;
&lt;p&gt;The architectural picture is now: two species of system, connected by a pipeline. Operational systems on the left, doing OLTP. Warehouses on the right, doing OLAP. ETL pipelines crossing the gap overnight. This was the dominant architecture for fifteen years, from roughly 1994 to 2010, and it is still how a lot of well-run analytical platforms work.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1979&lt;/td&gt;&lt;td&gt;Teradata founded — the first MPP analytical platform (shipped 1984)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1994&lt;/td&gt;&lt;td&gt;Sybase IQ ships — first commercial column store&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1996&lt;/td&gt;&lt;td&gt;Ralph Kimball publishes &lt;em&gt;The Data Warehouse Toolkit&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1998&lt;/td&gt;&lt;td&gt;MonetDB (CWI Amsterdam) advances columnar academic work&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2005&lt;/td&gt;&lt;td&gt;C-Store paper from Stonebraker et al. — basis for Vertica&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Different workloads need different storage layouts. The warehouse exists because OLTP and OLAP are not the same problem.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The warehouse made analytics tractable, but it was an appliance. You bought the hardware and software together. Storage and compute scaled in lockstep. The data that could go in had to fit a schema you&#39;d defined in advance. That last constraint is what broke next.&lt;/p&gt;
&lt;h2 id=&quot;chapter-4-the-internet-broke-the-schema-mid-2000s&quot;&gt;Chapter 4 — The internet broke the schema (mid-2000s)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/three-pressures.svg&quot; alt=&quot;Three simultaneous pressures on the warehouse model in the mid-2000s&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Web 2.0 pushed shapes the warehouse never expected through the door. JSON, web logs, clickstreams, video, sensor data. Schema-on-write meant the warehouse rejected anything it couldn&#39;t define up front — and most of the new data refused to define itself.&lt;/p&gt;
&lt;p&gt;Through the early 2000s, the warehouse model assumed that data arrived in a known shape. Operational systems had defined schemas. ETL pipelines knew the source columns and the target columns. The warehouse could enforce types, foreign keys, and business rules at the moment data was written. This is called &lt;strong&gt;schema-on-write&lt;/strong&gt;, and it was the warehouse&#39;s defining contract.&lt;/p&gt;
&lt;p&gt;Then the web and mobile and IoT happened. Web server logs in idiosyncratic formats. Clickstreams with thousands of optional event types. Mobile app analytics where the schema changed every release. JSON documents from APIs that nested arbitrarily. Sensor readings at high frequencies. None of this fit cleanly into a relational schema, and even when it could be coerced, the schema would change weekly.&lt;/p&gt;
&lt;h3 id=&quot;three-pressures-at-once&quot;&gt;Three pressures at once&lt;/h3&gt;
&lt;p&gt;The warehouse couldn&#39;t hold the new shapes, but the bigger problem was that it shouldn&#39;t try. Three pressures hit simultaneously:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Volume&lt;/strong&gt; — clickstreams and logs were two or three orders of magnitude bigger than transactional data. A retailer&#39;s transactions might be 10 million a day; their clickstream might be 100 million events.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Variety&lt;/strong&gt; — data was no longer just rows. JSON documents, key-value pairs, time series, graphs. Some of it had loose structure; some had no structure at all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Velocity&lt;/strong&gt; — the schema kept changing. Data engineers were being asked to ship a new column for the warehouse twice a week. Schema changes on a multi-petabyte warehouse were neither cheap nor reversible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The famous &quot;three Vs&quot; framing of big data came out of this period. It was a polite way of saying: the warehouse is not the right tool for everything that is now data.&lt;/p&gt;
&lt;p&gt;Engineering teams started keeping the new data on the side, in flat files on whatever storage they had — initially in HDFS, eventually in S3. The warehouse stayed for the structured analytical workloads it was good at. The new data lived elsewhere, with no schema enforcement, no transactions, and no real query engine on top of it. That accumulated pile of data would later get a name: the &lt;strong&gt;data lake&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Schema-on-write is a contract that demands the world hold still. The internet is what happens when the world doesn&#39;t.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The warehouse hadn&#39;t lost — it had run into a new requirement it was never designed to meet. What follows is how the field built a parallel infrastructure around the warehouse to handle the unstructured, the semi-structured, and the schema-changing — and how the rest of the modern stack is, in a sense, the long process of fixing that infrastructure&#39;s original sins.&lt;/p&gt;
&lt;h2 id=&quot;chapter-5-s3-changed-the-economics-2006&quot;&gt;Chapter 5 — S3 changed the economics (2006)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/s3-economics.svg&quot; alt=&quot;How S3 changed storage economics compared to appliance storage&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Object storage broke the economic constraint. &quot;Keep everything&quot; became a valid strategy for the first time in computing history. But cheap storage was not a database — high per-request latency, no transactions, no random writes.&lt;/p&gt;
&lt;p&gt;In March 2006, Amazon Web Services launched &lt;strong&gt;S3&lt;/strong&gt; — Simple Storage Service. The pricing was startling. Fifteen cents per gigabyte per month at launch, dropping over time to fractions of a cent. There was no minimum, no provisioning, no upfront commitment. You PUT a file, you GET a file, you DELETE a file, and Amazon billed you for what you actually stored.&lt;/p&gt;
&lt;p&gt;Compare this to the alternative. A traditional storage array required capital expenditure, capacity planning, and a storage administrator. A database that stored a petabyte required a hardware purchase that took months and was very hard to undo. S3 made storage so cheap and so elastic that, for the first time, the economically rational strategy was to keep &lt;em&gt;all&lt;/em&gt; the data, indefinitely, regardless of whether you knew what you&#39;d do with it later.&lt;/p&gt;
&lt;h3 id=&quot;what-cheap-storage-actually-was&quot;&gt;What &quot;cheap storage&quot; actually was&lt;/h3&gt;
&lt;p&gt;S3 wasn&#39;t a database. It was an HTTP API for storing and retrieving immutable blobs of bytes. Each object had a key, some bytes, some metadata, and that was it. There were no transactions, no indexes, no ability to update part of a file in place, and no native filesystem semantics. To &quot;modify&quot; a file, you uploaded a new version of the whole thing.&lt;/p&gt;
&lt;p&gt;The properties were unfamiliar to anyone coming from databases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Eventually consistent&lt;/strong&gt; (originally) — a PUT might not be visible to a GET on another machine for some seconds. Amazon fixed this in late 2020, but for the first fourteen years every system built on S3 had to handle eventual consistency explicitly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High per-request latency&lt;/strong&gt; — a GET of a small file took tens to hundreds of milliseconds, not the microseconds of a local disk. IOPS were terrible compared to local SSD.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High aggregate throughput&lt;/strong&gt; — but if you read large objects in parallel, you got hundreds of megabytes per second per object, scaling linearly with concurrency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP range requests&lt;/strong&gt; — you could ask for just bytes 1000–2000 of an object instead of the whole thing. This turns out to matter enormously for what comes next.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Effectively infinite&lt;/strong&gt; — no capacity planning, no provisioning, no failed disks for the user to think about. Eleven nines of durability.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-mismatch-with-databases&quot;&gt;The mismatch with databases&lt;/h3&gt;
&lt;p&gt;These properties did not match what a database expects from storage. Databases assume small, fast, random-access I/O — the model of a local disk. S3 was the opposite: large, slow, immutable. A database that ran directly on S3 with no architectural changes would be unusably slow.&lt;/p&gt;
&lt;p&gt;But the economics were so different that engineers were willing to redesign databases to fit S3, rather than the other way around. The next chapters are the story of that redesign. File formats had to change (Parquet). Engines had to change (Spark and the interactive SQL engines that followed). And eventually a new layer had to be invented above the files — the table format — because the lake by itself was not yet a database.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;2003&lt;/td&gt;&lt;td&gt;Google File System paper (the inspiration for HDFS)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2006&lt;/td&gt;&lt;td&gt;Amazon S3 launches; Hadoop becomes a top-level Apache project&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2008&lt;/td&gt;&lt;td&gt;Cloudera and Hortonworks form to commercialize Hadoop&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2010&lt;/td&gt;&lt;td&gt;Azure Blob Storage, OpenStack Swift, Google Cloud Storage&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Cheap storage is a tectonic shift. It doesn&#39;t just change cost — it changes what&#39;s worth keeping. And what&#39;s worth keeping changes what&#39;s worth building.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;S3 created the data lake by accident. It didn&#39;t intend to compete with databases. It just made storage so cheap that engineers started using it for everything, and the rest of the stack had to catch up. The catch-up took ten years.&lt;/p&gt;
&lt;h2 id=&quot;chapter-6-storage-solved-querying-broken-2006-2008&quot;&gt;Chapter 6 — Storage solved. Querying broken. (2006–2008)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/lake-storage-vs-query.svg&quot; alt=&quot;The lake era&amp;#39;s gap: cheap storage below, slow disk-bound querying above&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Hadoop and Hive gave analysts SQL on the lake. Under the hood, every query compiled into chains of MapReduce jobs that hit disk between every stage. It worked. It was not fast.&lt;/p&gt;
&lt;p&gt;With cheap storage in place, the question became: how do we query this stuff? In 2006 Hadoop had emerged from Doug Cutting&#39;s work at Yahoo, implementing the ideas of Google&#39;s File System paper (2003) and the MapReduce paper (2004). &lt;strong&gt;HDFS&lt;/strong&gt; gave you a place to put files. &lt;strong&gt;MapReduce&lt;/strong&gt; gave you a way to run code over them. Together they were a usable, scalable batch processing platform — but only for engineers willing to write Java.&lt;/p&gt;
&lt;p&gt;In 2008, Facebook released &lt;strong&gt;Hive&lt;/strong&gt;. Hive translated SQL into chains of MapReduce jobs. An analyst could write &lt;code&gt;SELECT region, SUM(amt) FROM orders GROUP BY region&lt;/code&gt; and Hive would compile that into one or more MapReduce stages, run them across the cluster, and return the result. SQL had arrived on the lake.&lt;/p&gt;
&lt;h3 id=&quot;why-it-was-slow-disk-between-every-stage&quot;&gt;Why it was slow: disk between every stage&lt;/h3&gt;
&lt;p&gt;The MapReduce model had a fundamental performance ceiling. Every map phase wrote its output to local disk. Every reduce phase read its input from disk. If the query needed multiple stages — and most non-trivial queries did — each stage&#39;s output was written to disk before the next stage read it back. A query with three stages did three full disk-write-disk-read cycles. Even on fast disks, this dominated execution time.&lt;/p&gt;
&lt;p&gt;The reason for the disk-between-stages design was fault tolerance. If a node died midway through a long-running job, MapReduce could restart just the affected task by re-reading its inputs from disk. This was a deliberate trade: correctness and resilience over speed. For overnight batch jobs on enormous datasets, that was the right trade. For analysts who wanted to iterate on queries interactively, it was unbearable.&lt;/p&gt;
&lt;h3 id=&quot;what-we-lost-relative-to-the-warehouse&quot;&gt;What we lost relative to the warehouse&lt;/h3&gt;
&lt;p&gt;The Hadoop/Hive lake gave us scale and openness, but at the cost of nearly everything the warehouse provided:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ACID semantics.&lt;/strong&gt; Hive had no transactions worth the name. Concurrent writers could corrupt tables.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schema enforcement.&lt;/strong&gt; Hive&#39;s metastore had a schema, but enforcing it depended on the writer&#39;s good behavior, not the system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real indexing.&lt;/strong&gt; Some bolt-on solutions existed, but the lake had nothing like the database&#39;s first-class index facilities.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactive query latency.&lt;/strong&gt; Even simple queries took seconds to minutes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update and delete.&lt;/strong&gt; The lake was append-only by design. Modifying rows required rewriting whole partitions.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;SQL is the universal API for data. Every analytical system eventually exposes it — even when the underlying execution model has nothing to do with SQL.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Hive solved the access problem but exposed two new ones: the engine was too slow for interactive work, and the file formats it queried (text, CSV, sequence files) were terrible for analytics. Both got fixed over the next five years. Faster engines came first, but the file format work mattered more in the long run.&lt;/p&gt;
&lt;h2 id=&quot;chapter-7-columns-came-to-the-lake-2013&quot;&gt;Chapter 7 — Columns came to the lake (2013)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/parquet-anatomy.svg&quot; alt=&quot;Anatomy of a Parquet file: row groups, column chunks, footer statistics&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Parquet&#39;s anatomy is the answer to S3&#39;s physics. One self-describing file holds many row groups; each row group holds columns laid out together; the footer indexes everything. An engine reads the footer, decides which byte ranges to fetch, and skips the rest.&lt;/p&gt;
&lt;p&gt;In 2013, Twitter and Cloudera jointly released &lt;strong&gt;Apache Parquet&lt;/strong&gt;. The project drew its design from Google&#39;s Dremel paper (2010), which described how Google stored and queried nested data internally. Parquet brought columnar storage — the warehouse innovation from 1994 — to the data lake, in a file format that was open, language-agnostic, and tuned for object storage.&lt;/p&gt;
&lt;p&gt;Parquet&#39;s importance is hard to overstate. It is the file format the entire modern lakehouse is built on. Iceberg tables, Snowflake external tables, DuckDB on S3 — they are all reading and writing the same Parquet files. The format won the way TCP/IP won: by being open, simple enough to implement everywhere, and good enough to defeat the alternatives.&lt;/p&gt;
&lt;h3 id=&quot;anatomy-of-a-parquet-file&quot;&gt;Anatomy of a Parquet file&lt;/h3&gt;
&lt;p&gt;A Parquet file is a magic-byte header, followed by one or more &lt;strong&gt;row groups&lt;/strong&gt;, followed by a footer (the metadata), followed by a closing magic byte. Each row group is a horizontal slice of the table — typically 128MB to 1GB worth of rows. Within a row group, the data is laid out column by column: all the values of column A first, then all the values of column B, and so on.&lt;/p&gt;
&lt;p&gt;The footer is the trick. It holds the schema; the offset of every row group&#39;s every column chunk; per-column statistics (min, max, null count, row count) for every row group; and pointers to compression codecs and encodings. To answer a query, an engine first issues a small range request for the footer. Then it knows exactly which bytes hold the columns it needs, and issues parallel range requests for those bytes only. Everything else stays on S3.&lt;/p&gt;
&lt;p&gt;This is what makes Parquet on S3 economically viable for analytics. Without the footer index, an engine would have to download whole files just to figure out what was in them. With the footer index plus column-grouped layout plus HTTP range requests, the engine downloads the minimum bytes needed.&lt;/p&gt;
&lt;h3 id=&quot;two-query-optimizations-live-in-this-layout&quot;&gt;Two query optimizations live in this layout&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Column pruning.&lt;/strong&gt; The query needs columns A and C? Read only the byte ranges for A and C. Skip B, D, E.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Predicate pushdown.&lt;/strong&gt; The query has &lt;code&gt;WHERE region = &#39;US&#39;&lt;/code&gt;? Look at the per-row-group min/max statistics for the &lt;em&gt;region&lt;/em&gt; column. If a row group&#39;s range is &lt;code&gt;[&#39;EU&#39;, &#39;EU&#39;]&lt;/code&gt;, skip it entirely — no rows in it can match.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compression matters too. Within a column chunk, all values share a type, which makes compression dramatically more effective than on a row store. Parquet supports dictionary, run-length, and bit-packing encodings plus general-purpose compression (Snappy, Gzip, Zstd) on top. A typical Parquet file is 5–10x smaller than the same data in CSV.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;2010&lt;/td&gt;&lt;td&gt;Google publishes the Dremel paper&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2013&lt;/td&gt;&lt;td&gt;Twitter + Cloudera release Apache Parquet&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2015&lt;/td&gt;&lt;td&gt;Parquet becomes a top-level Apache project&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2016+&lt;/td&gt;&lt;td&gt;Universal adoption: Spark, Hive, Impala, Snowflake, BigQuery, DuckDB&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Match your file format to the physics of your storage layer. One large self-describing file beats thousands of small ones. Range requests beat full reads. Column locality beats row locality for analytics.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;chapter-8-the-in-memory-engines-made-it-interactive-2010-2012&quot;&gt;Chapter 8 — The in-memory engines made it interactive (2010–2012)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/compute-storage-split.svg&quot; alt=&quot;The structural break: compute engines reading open formats from storage they don&amp;#39;t own&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The new engines didn&#39;t own the data. They read open formats from object storage, computed in memory, and went away. Storage and compute scaled independently for the first time — a structural break from the appliance model.&lt;/p&gt;
&lt;p&gt;Two engines fixed Hive&#39;s interactivity problem in the early 2010s. Both kept state in memory between stages instead of writing it to disk; both treated the storage layer as something they didn&#39;t own.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apache Spark&lt;/strong&gt; came out of UC Berkeley&#39;s AMPLab in 2009 and was open-sourced in 2010. Matei Zaharia&#39;s PhD thesis introduced the Resilient Distributed Dataset — a model where intermediate results stayed in memory across stages, with lineage tracked so lost partitions could be recomputed on failure. Where MapReduce hit disk between every stage, Spark hit disk only when memory ran out or the user explicitly asked.&lt;/p&gt;
&lt;p&gt;A second wave of &lt;strong&gt;interactive SQL engines&lt;/strong&gt; emerged inside the large web companies around 2012, designed from day one for ad-hoc analytical queries. They fetched data from many sources, computed in memory, and didn&#39;t persist anything between queries. A typical query that took ten minutes on Hive took ten seconds on this generation of engines.&lt;/p&gt;
&lt;h3 id=&quot;the-structural-break-compute-leaves-storage-behind&quot;&gt;The structural break: compute leaves storage behind&lt;/h3&gt;
&lt;p&gt;The deeper change wasn&#39;t performance. It was the relationship between compute and storage. In the warehouse era, compute and storage were bundled in a single appliance. In the Hive era, compute and storage ran on the same physical cluster, even though they were different software layers.&lt;/p&gt;
&lt;p&gt;Spark and the interactive engines broke that. They read data from wherever — HDFS, S3, a JDBC source, a Kafka topic — computed over it in their own process, and returned results. The storage layer didn&#39;t know the engine existed. The engine didn&#39;t own the storage. They communicated through an open file format (often Parquet by this point) and an object-storage API.&lt;/p&gt;
&lt;p&gt;The &quot;thin wire&quot; between compute and storage is, in practice, a file format spec plus an object-storage API. As long as an engine can read Parquet and speak S3, it can join the party. This is what lets Spark, DuckDB, Snowflake, and every engine since operate on the same files — and it is the architectural pattern the rest of the modern stack inherited.&lt;/p&gt;
&lt;h3 id=&quot;independent-scaling&quot;&gt;Independent scaling&lt;/h3&gt;
&lt;p&gt;Decoupling compute from storage had an operational consequence: they could be scaled independently. Need to run a very large query? Spin up more compute for an hour. Data grew? Only storage scales. This had not been true of the warehouse era, where buying more storage meant buying more boxes with more compute attached, whether or not you needed it.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;2009&lt;/td&gt;&lt;td&gt;Spark prototyped at Berkeley AMPLab&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2010&lt;/td&gt;&lt;td&gt;Spark open-sourced&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2012&lt;/td&gt;&lt;td&gt;Interactive SQL engines emerge inside the large web companies&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2013&lt;/td&gt;&lt;td&gt;Spark becomes an Apache top-level project&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Decouple compute from storage and you can scale them independently. The contract between them is now a file format. Anyone speaking the format can play. Lock-in collapses.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Once compute and storage came apart, the question was no longer &quot;which appliance?&quot; but &quot;which engine, on which storage, for which workload?&quot; That question is still being answered — and it is the question Dataglot exists to answer well: an engine that speaks the same open formats can be adopted without migrating any data.&lt;/p&gt;
&lt;p&gt;The lake now had cheap storage, good files, and fast engines. What it didn&#39;t have was a real &lt;em&gt;table&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;chapter-9-snowflake-separated-everything-2014&quot;&gt;Chapter 9 — Snowflake separated everything (2014)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/snowflake-separation.svg&quot; alt=&quot;Snowflake&amp;#39;s commercial separation of storage, compute, and services&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Snowflake (general availability 2014) made the three-layer separation a commercial product. Storage in S3, compute as elastic warehouses, services and metadata as a managed layer. The warehouse re-emerged in cloud form — proving the model worked at scale.&lt;/p&gt;
&lt;p&gt;Snowflake&#39;s first beta was 2012; general availability was 2014. The architecture was unusual at the time. Storage was Amazon S3. Compute was &quot;virtual warehouses&quot; — clusters that customers could spin up, resize, suspend, and clone independently. The catalog and metadata services were a Snowflake-managed layer that all the warehouses talked to. These three pieces — storage, compute, services — could each be scaled, billed, and operated independently.&lt;/p&gt;
&lt;p&gt;From a customer&#39;s point of view, this was magic. You could leave the data in place, spin up a &quot;small&quot; warehouse for a regular reporting workload and a &quot;4XL&quot; warehouse for a one-off analytical job, and have them both reading the same tables at the same time without contention. Storage cost almost nothing. Compute cost what you used and nothing else.&lt;/p&gt;
&lt;h3 id=&quot;what-snowflake-proved&quot;&gt;What Snowflake proved&lt;/h3&gt;
&lt;p&gt;Snowflake&#39;s commercial success — IPO in 2020 at one of the largest software valuations in history — proved several things that mattered architecturally:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The three-layer separation worked at scale.&lt;/strong&gt; Customers ran serious workloads. The architecture wasn&#39;t a curiosity; it was production-grade.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Object storage was good enough.&lt;/strong&gt; Snowflake stored the underlying data in S3 (or equivalents). The latency penalty was manageable; the economics were unbeatable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The catalog was the lock-in.&lt;/strong&gt; Snowflake&#39;s storage format was proprietary; customers couldn&#39;t take their data and run it through someone else&#39;s engine. The metadata, the optimizer, and the SQL layer were where Snowflake earned its margin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last point matters for what comes next. Snowflake had separated storage, compute, and catalog architecturally — but kept all three under one vendor&#39;s roof. This was acceptable in 2014 because the alternative — running and tuning your own warehouse — was much worse. But it left a strategic opening. If the same three-layer separation could work with &lt;em&gt;open specs&lt;/em&gt; at every layer, customers could keep their data on their own storage, in an open format, and choose the engine they wanted on top. That was the next architectural move.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;2012&lt;/td&gt;&lt;td&gt;Snowflake founded; Amazon Redshift launches&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2014&lt;/td&gt;&lt;td&gt;Snowflake reaches general availability&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2017&lt;/td&gt;&lt;td&gt;Google BigQuery becomes broadly adopted&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2020&lt;/td&gt;&lt;td&gt;Snowflake IPO&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Three layers, scaled independently, billed separately. Snowflake proved the architecture commercially. The remaining question was whether each layer could be open.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;chapter-10-a-pile-of-files-is-not-a-table-2014-2016&quot;&gt;Chapter 10 — A pile of files is not a table (~2014–2016)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/files-vs-table.svg&quot; alt=&quot;Why a directory of files is not a table: no transactions, no schema history, no statistics&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The lake had cheap storage, good files, fast engines. What it didn&#39;t have was a real table. The Hive Metastore tried — and broke at petabyte scale.&lt;/p&gt;
&lt;p&gt;By 2014, the open lake had three of the four layers it needed. What was missing was a coordination layer that would turn a directory of Parquet files into something that behaved like a table — atomic transactions, schema evolution, time travel, safe concurrent writers.&lt;/p&gt;
&lt;p&gt;The placeholder was the &lt;strong&gt;Hive Metastore&lt;/strong&gt;, built in 2008 as a relational database tracking Hive&#39;s tables and partitions. It worked well enough for Hive&#39;s batch workloads. As people started running Spark and other engines against the same data, and as table sizes grew into the petabyte range, its limits became failure modes.&lt;/p&gt;
&lt;h3 id=&quot;the-four-failure-modes&quot;&gt;The four failure modes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;O(n) query planning.&lt;/strong&gt; The metastore tracked tables and partitions, but not individual files. To plan a query, the engine had to &lt;em&gt;list&lt;/em&gt; the relevant directories on S3. At petabyte scale, with hundreds of thousands of partitions and millions of files, the LIST calls themselves became a major fraction of query time. Some queries spent more time planning than executing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No atomic commits.&lt;/strong&gt; S3 has no native rename. To &quot;atomically&quot; replace a file, the convention was write-then-rename — but S3 rename is copy-then-delete, two separate operations that can fail in the middle. A failed write left the table in a state where some new files were visible and others were missing. Readers saw partial results. There was no rollback because there was no concept of a transaction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No safe schema evolution.&lt;/strong&gt; Hive resolved column references by name. If a column was renamed, files written before the rename had the old name and files written after had the new one. Some readers got the new name. Some failed. Some silently returned wrong results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Concurrent writers corrupt.&lt;/strong&gt; With multiple engines writing to the same table, there was no coordination protocol. Two writers could overlap, one&#39;s changes could overwrite the other&#39;s, and the metastore had no way to detect it. Production teams added external locking with Zookeeper or by convention. Convention failed. Locking was fragile.&lt;/p&gt;
&lt;p&gt;Each individual problem had workarounds. Each workaround was complicated. Together they meant that running the lake at scale required a small team of specialists watching the system constantly. This is not what a &quot;table&quot; is supposed to require.&lt;/p&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Without a transactional catalog, you don&#39;t have a database — you have files. Read the four failures as a specification: whoever built the next table format had to provide O(1) planning, atomic commits without rename, safe schema evolution, and serializable concurrent writes.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Netflix&#39;s team did exactly this in 2017.&lt;/p&gt;
&lt;h2 id=&quot;chapter-11-netflix-turned-files-into-tables-2017&quot;&gt;Chapter 11 — Netflix turned files into tables (2017)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/iceberg-metadata-tree.svg&quot; alt=&quot;Iceberg&amp;#39;s metadata tree: catalog pointer, metadata files, manifests, data files&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The whole table — every snapshot, every file, every statistic — is reachable from a single root pointer. A commit is a swap of that pointer. That&#39;s how Iceberg makes ACID transactions on a pile of immutable files.&lt;/p&gt;
&lt;p&gt;Ryan Blue and Daniel Weeks at Netflix started designing what became &lt;strong&gt;Apache Iceberg&lt;/strong&gt; in 2017. Netflix had hit every Hive Metastore failure at production scale. They built an alternative, open-sourced it in 2018, and donated it to Apache, where it became a top-level project in 2020.&lt;/p&gt;
&lt;p&gt;Iceberg&#39;s design is conceptually simple: store the entire description of a table in a tree of metadata files in object storage, with a single root pointer at the top. To commit a change, write new metadata files describing the new state, then atomically swap the root pointer. Old metadata stays where it was — you can read older versions of the table just by pointing at older roots. This one mechanism gives Iceberg time travel, rollback, and snapshot isolation.&lt;/p&gt;
&lt;h3 id=&quot;the-metadata-hierarchy&quot;&gt;The metadata hierarchy&lt;/h3&gt;
&lt;p&gt;Walk the tree top-down:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Root pointer&lt;/strong&gt; — a single file (typically &lt;code&gt;metadata.json&lt;/code&gt;) that names the current snapshot. The catalog stores this pointer. A commit is an atomic swap of which file the catalog points at.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manifest list&lt;/strong&gt; — for the current snapshot, the list of all manifest files plus partition-level statistics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manifest file&lt;/strong&gt; — an index of data files, with per-file statistics: column min/max, null counts, row counts. This is what lets Iceberg plan queries in O(1) without listing S3 directories.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data files&lt;/strong&gt; — the actual Parquet files. Immutable. Updates work by writing new data files plus delete files; the old data stays where it is, which is what makes time travel and rollback work.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-each-hive-failure-gets-fixed&quot;&gt;How each Hive failure gets fixed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;O(n) planning becomes O(1).&lt;/strong&gt; The engine reads one metadata file and follows pointers, instead of listing thousands of S3 directories.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Atomic commits work via pointer swap.&lt;/strong&gt; The catalog&#39;s update of the root pointer is a single atomic operation — either it happened or it didn&#39;t. No half-states.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schema evolution works on column IDs, not names.&lt;/strong&gt; Iceberg assigns each column a stable numeric ID at creation. Renaming a column changes the name in metadata but not the ID. Readers reference the ID and find the data correctly across versions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Concurrent writers are serialized.&lt;/strong&gt; Two writers each prepare their new metadata and both attempt to swap the root pointer. The catalog&#39;s atomic compare-and-swap lets exactly one win. The loser retries against the new state. No corruption, no locks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-snapshot-isolation-gives-you-for-free&quot;&gt;What snapshot isolation gives you for free&lt;/h3&gt;
&lt;p&gt;Because old metadata is kept until explicitly expired, readers always read against one consistent snapshot. While a writer commits, in-flight readers continue reading the previous snapshot, uninterrupted. Time travel and rollback fall out the same way: want the table as it was last Tuesday? Read against that snapshot. Want to undo a bad write? Swap the root pointer back. These features are not bolted on — they are inherent in keeping snapshots around.&lt;/p&gt;
&lt;p&gt;Two competing table formats appeared around the same time. &lt;strong&gt;Delta Lake&lt;/strong&gt; (Databricks, 2017) was Spark-first by design, with a transaction-log-based metadata model. &lt;strong&gt;Apache Hudi&lt;/strong&gt; (Uber, 2016) was streaming-first, optimized for row-level upserts and CDC. All three now solve roughly the same problems with different bets, and they have been converging — but Iceberg has the broadest multi-vendor adoption (Snowflake, Spark, DuckDB, Athena, BigQuery all read it) and the most engine-neutral design philosophy.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/table-format-bets.svg&quot; alt=&quot;Three table formats, three different original bets&quot; /&gt;&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;2017&lt;/td&gt;&lt;td&gt;Design starts at Netflix&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2018&lt;/td&gt;&lt;td&gt;Open-sourced; donated to Apache&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2020&lt;/td&gt;&lt;td&gt;Top-level Apache project&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2024&lt;/td&gt;&lt;td&gt;Snowflake announces support; Databricks acquires Tabular; de facto standard for the open lakehouse&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Open specifications win because the network effect compounds. The table format is the thinnest possible contract between writers, readers, and storage — and once everyone agrees on it, lock-in evaporates.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Iceberg is the keystone of the modern open lakehouse. Dataglot is built to be a first-class Iceberg engine — it reads and writes Iceberg tables natively, with no proprietary intermediate format anywhere.&lt;/p&gt;
&lt;h2 id=&quot;chapter-12-arrow-the-connective-tissue-2016&quot;&gt;Chapter 12 — Arrow, the connective tissue (2016)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/arrow-n-squared.svg&quot; alt=&quot;The N-squared serialization problem Arrow solved with one shared in-memory format&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Every engine had its own in-memory layout. Crossing from Spark to pandas to a database meant constant serialization. With N systems, you needed N² converters. Arrow standardized the in-memory format itself.&lt;/p&gt;
&lt;p&gt;A historical note on order: Arrow was open-sourced in 2016, before Iceberg&#39;s 2017 design. It belongs &lt;em&gt;here&lt;/em&gt; in the narrative because it is best understood as the in-memory complement to Parquet&#39;s on-disk story. Parquet standardized the columnar layout on disk; Arrow standardized the columnar layout in memory. Together they let data move through the modern stack without conversion taxes at any layer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apache Arrow&lt;/strong&gt; was started by Wes McKinney (creator of pandas) and Jacques Nadeau (Drill, Dremio) along with collaborators from across the analytical ecosystem. The project&#39;s defining commitment is a precise, language-agnostic specification of how columnar data is laid out in RAM. Once two systems both implement the spec, they can share data without copying or transforming it — even when they&#39;re written in different languages.&lt;/p&gt;
&lt;h3 id=&quot;the-n2-problem-arrow-solved&quot;&gt;The N² problem Arrow solved&lt;/h3&gt;
&lt;p&gt;Before Arrow, every analytical engine had its own in-memory representation. Spark had Project Tungsten&#39;s binary format. pandas had NumPy-backed columns. Drill had value vectors. When data moved between systems — a Spark job feeding a pandas analysis, a SQL engine&#39;s result feeding a Python ML model — every boundary required serialization on one side and deserialization on the other.&lt;/p&gt;
&lt;p&gt;With N different systems, the ecosystem was building roughly N² conversion paths. Worse, serialization is not free: at scale, the conversion CPU and memory cost dominated end-to-end time. Some workloads spent more time converting between formats than computing.&lt;/p&gt;
&lt;p&gt;Arrow inverts the topology. Every system implements the Arrow spec; conversions happen at the edges of each system, not at every pair. With 6 systems, you need 6 implementations, not 15 converter paths. And because the in-memory layout is identical across systems, two processes can share the same memory pages directly — zero-copy. The bytes don&#39;t need to be touched at all.&lt;/p&gt;
&lt;h3 id=&quot;arrow-flight-the-wire-protocol&quot;&gt;Arrow Flight: the wire protocol&lt;/h3&gt;
&lt;p&gt;Beyond the in-memory format, the project ships &lt;strong&gt;Arrow Flight&lt;/strong&gt; — a wire protocol for moving Arrow batches over the network. Flight replaces row-by-row protocols like ODBC and JDBC with columnar batches over gRPC. For analytical workloads that move millions of rows, this is dramatically more efficient — orders of magnitude in some benchmarks.&lt;/p&gt;
&lt;h3 id=&quot;why-this-matters-for-dataglot&quot;&gt;Why this matters for Dataglot&lt;/h3&gt;
&lt;p&gt;Dataglot is Arrow-native end to end. Connectors return Arrow batches. The execution engine runs over Arrow. Results leave the system as Arrow. There is no internal serialization tax — which matters most in federation, where data crosses many source and process boundaries on its way to one result set.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Year&lt;/th&gt;&lt;th&gt;Event&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;2015&lt;/td&gt;&lt;td&gt;Wes McKinney and Jacques Nadeau begin discussions&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2016&lt;/td&gt;&lt;td&gt;Apache Arrow announced&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2018&lt;/td&gt;&lt;td&gt;Arrow Flight introduced&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2020+&lt;/td&gt;&lt;td&gt;Adoption across pandas, Spark, BigQuery, Snowflake, DuckDB, DataFusion, ClickHouse&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;The cost of crossing system boundaries dominates large workloads. Standardizing the in-memory format is what makes the boundaries cheap.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If Parquet and Iceberg are the open contracts on disk, Arrow is the open contract in RAM. The last two chapters put all six layers together — and walk through where Dataglot builds on each one.&lt;/p&gt;
&lt;h2 id=&quot;chapter-13-the-stack-converged&quot;&gt;Chapter 13 — The stack converged&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/open-stack-layers.svg&quot; alt=&quot;The open lakehouse stack: six layers, each an open spec, engines swappable on top&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A layered, spec-driven stack. Each layer is independently swappable. Storage and compute scale separately. Catalogs are open. Engines compete on execution quality, not data lock-in.&lt;/p&gt;
&lt;p&gt;The cumulative result of the history is the modern open lakehouse: a six-layer stack where every layer has an open specification and every layer can be replaced without rewriting the others.&lt;/p&gt;
&lt;h3 id=&quot;the-six-layers-top-to-bottom&quot;&gt;The six layers, top to bottom&lt;/h3&gt;
&lt;p&gt;Read them top to bottom. Each layer&#39;s job is to make the layer above it work without owning the data.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Layer&lt;/th&gt;&lt;th&gt;What lives there&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Compute&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;The query engines: Spark, DuckDB, Dataglot, and the rest. Each speaks the open specs below. Stateless and elastic — spin up for a query, spin down. Engines compete on execution quality, not on owning your data.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;In-memory&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Apache Arrow. The columnar byte layout every engine reads and writes. Zero-copy across language boundaries. Eliminates the serialization tax at engine handoffs.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Catalog&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;The transactional table directory. The Iceberg REST catalog spec lets multiple engines safely share the same tables. Polaris and Lakekeeper are open implementations.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Table format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Apache Iceberg (plus Delta Lake and Hudi for specific workloads). Turns a pile of immutable files into a transactional, time-traveling, schema-evolving table.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;File format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Apache Parquet, near-universally. Self-describing columnar files with a footer index, optimized for object storage via byte-range requests.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Object storage: S3, GCS, ADLS, MinIO for self-hosted. Cheap, durable, infinite. The same Parquet files can live on any of them — you can change vendor without rewriting data.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;the-structural-insight&quot;&gt;The structural insight&lt;/h3&gt;
&lt;p&gt;Look back at chapter 1. In 1970, all six layers were one rectangle — a single process that owned the tables, the engine, the log, and the access controls. Today, all six layers are separate, swappable, and governed by open specs. That progression — from a single bundled appliance to six independently-replaceable layers — is the entire fifty-year argument.&lt;/p&gt;
&lt;p&gt;The architectural point of the lakehouse isn&#39;t just &quot;open formats.&quot; It is that &lt;em&gt;every layer is replaceable independently&lt;/em&gt;. You can change your engine without touching your data. You can change your storage without touching your engine. You can change your catalog without rewriting either. This is what eliminates lock-in — not openness in any one place, but the systematic decoupling of every layer from every other.&lt;/p&gt;
&lt;h3 id=&quot;where-the-competitive-battle-is&quot;&gt;Where the competitive battle is&lt;/h3&gt;
&lt;p&gt;With the lower layers (storage, files, table format) commoditized, the competitive question moves up. Two layers are still genuinely contested:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The compute layer&lt;/strong&gt; — engines compete on execution quality, on which workloads they&#39;re best at, on developer experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The catalog layer&lt;/strong&gt; — semantic metadata, governance, multi-tenancy, business meaning. The catalog wraps the table format and adds the things that turn raw tables into a usable platform.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dataglot competes in the compute layer — with governance enforcement as a first-class engine capability rather than an add-on that wraps the engine.&lt;/p&gt;
&lt;div class=&quot;callout callout--info&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;16&quot; x2=&quot;12&quot; y2=&quot;12&quot;/&gt;&lt;line x1=&quot;12&quot; y1=&quot;8&quot; x2=&quot;12.01&quot; y2=&quot;8&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;Take-away&lt;/p&gt;&lt;p&gt;Tightly-coupled appliances became loosely-coupled, spec-driven layers. The architecture that won is the one that minimizes lock-in by maximizing replaceability.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;chapter-14-why-dataglot&quot;&gt;Chapter 14 — Why Dataglot&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/dataglot-on-the-stack.svg&quot; alt=&quot;Dataglot on the open stack: the governed compute layer over Iceberg, Parquet, and your object storage&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Same six layers. Specific choices at each one. Every decision is defensible by pointing back at the chapter that motivated it. There are no surprises.&lt;/p&gt;
&lt;h3 id=&quot;compute-dataglot-itself&quot;&gt;Compute — Dataglot itself&lt;/h3&gt;
&lt;p&gt;Built in &lt;strong&gt;Rust&lt;/strong&gt;: vectorized, SIMD-aware execution with memory safety guaranteed by the language. What that buys &lt;em&gt;you&lt;/em&gt; is an engine that starts in milliseconds, ships as one static binary, and doesn&#39;t carry a JVM&#39;s memory ceremony or garbage-collection pauses into your query latencies — and an engine that doesn&#39;t segfault is an engine you can trust with production credentials. Under the hood it builds on proven Apache foundations (DataFusion for query execution) rather than reinventing them. &lt;em&gt;(See chapter 8 on why fast vectorized engines matter, and chapter 12 on Arrow as the in-memory currency.)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;in-memory-apache-arrow&quot;&gt;In-memory — Apache Arrow&lt;/h3&gt;
&lt;p&gt;Native end to end. Connectors return Arrow batches. Execution stays Arrow. Results leave as Arrow. No internal serialization tax — which matters most in federation, where a single query&#39;s data crosses many source and process boundaries. &lt;em&gt;(See chapter 12.)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;catalog-open-iceberg-rest&quot;&gt;Catalog — open Iceberg REST&lt;/h3&gt;
&lt;p&gt;Dataglot works with open Iceberg REST catalog implementations such as Lakekeeper — multi-tenant, secure, standards-compliant. The open catalog spec is what guarantees you can leave whenever you want: your tables stay readable by any Iceberg-aware engine. &lt;em&gt;(See chapter 10 on why a real catalog matters and chapter 13 on the open catalog layer.)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;table-format-apache-iceberg&quot;&gt;Table format — Apache Iceberg&lt;/h3&gt;
&lt;p&gt;Open spec. Engine-neutral. Data is stored in plain Iceberg tables that any Iceberg-aware engine — including yours — can read or write. There is no proprietary intermediate format anywhere. &lt;em&gt;(See chapter 11.)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;file-format-apache-parquet&quot;&gt;File format — Apache Parquet&lt;/h3&gt;
&lt;p&gt;The physical format under Iceberg. Open spec, columnar, compressed, range-fetch friendly. The reason caching and federation can be efficient even when source systems are slow. &lt;em&gt;(See chapter 7.)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;storage-your-object-storage&quot;&gt;Storage — your object storage&lt;/h3&gt;
&lt;p&gt;Data lives in your object storage, not anyone else&#39;s. Your bucket. Your security perimeter. Your compliance boundary. Dataglot operates on it through standard S3 APIs — you keep control. This is the architectural foundation for serving regulated industries: data never leaves your domain. &lt;em&gt;(See chapter 5 on the economics that made this possible and chapter 9 on why the three-layer separation is the winning move.)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-follows-from-these-choices&quot;&gt;What follows from these choices&lt;/h3&gt;
&lt;p&gt;Three properties fall out of the architecture:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No data lock-in.&lt;/strong&gt; The data is in your bucket, in Iceberg tables, in Parquet files. You can leave at any time. Any other Iceberg-aware engine reads the same tables.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Independent scaling.&lt;/strong&gt; Compute scales for the workload. Storage scales for the data. Catalog stays small. Three layers, three cost curves, three operational regimes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federation across sources.&lt;/strong&gt; Because the in-memory layer is Arrow and connectors return Arrow, federating across heterogeneous sources — databases, lakehouses, files — is architecturally clean, and materialization into Iceberg turns slow sources into fast ones.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And one property is layered on top of all of them: &lt;strong&gt;governance compiled into the plan&lt;/strong&gt;. Because Dataglot owns the query plan end to end, column masks and row filters are typed expressions baked into every scan — not SQL rewrites in front of the engine, not filters behind it. The open stack made the layers swappable; Dataglot&#39;s contribution is making the compute layer &lt;em&gt;provably governed&lt;/em&gt;. That story is the subject of the &lt;a href=&quot;/guides/plan-time-governance/&quot;&gt;plan-time governance guide&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;callout callout--success&quot;&gt;&lt;span class=&quot;callout__icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;20&quot; height=&quot;20&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M22 11.08V12a10 10 0 1 1-5.93-9.14&quot;/&gt;&lt;polyline points=&quot;22 4 12 14.01 9 11.01&quot;/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;div class=&quot;callout__body&quot;&gt;&lt;p class=&quot;callout__title&quot;&gt;The closing argument&lt;/p&gt;&lt;p&gt;Standing on the shoulders of giants is faster than reinventing them. Open-spec compatible end to end. Your data, your bucket, your control. Dataglot is the engine — the rest is the open lakehouse.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;looking-back-the-whole-arc-three-ways&quot;&gt;Looking back: the whole arc, three ways&lt;/h2&gt;
&lt;p&gt;Three one-glance recaps of the same fifty years.&lt;/p&gt;
&lt;h3 id=&quot;the-rhythm-of-the-timeline&quot;&gt;The rhythm of the timeline&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/five-decades-timeline.svg&quot; alt=&quot;Five decades of data architecture on a single timeline&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Three things to notice when you lay every event on one axis. First, &lt;strong&gt;the warehouse era is long&lt;/strong&gt; — almost twenty years from Sybase IQ to Snowflake. The architecture wasn&#39;t broken; it just needed a different economic regime to evolve. Second, &lt;strong&gt;the lake era is dense&lt;/strong&gt; — Hadoop, Hive, Parquet, and Spark all clustered between 2006 and 2013. Once cheap storage existed, the surrounding ecosystem filled in fast. Third, &lt;strong&gt;the table format era is recent&lt;/strong&gt; — Iceberg, Delta, Hudi all 2016–2017. The lake had been around for a decade by then; the catalog problem was the last piece to be solved.&lt;/p&gt;
&lt;h3 id=&quot;each-generation-pulled-one-layer-apart&quot;&gt;Each generation pulled one layer apart&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/layer-separation-eras.svg&quot; alt=&quot;Each generation pulled one more layer out of the monolith&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The 1970s rectangle became the 2020s six-layer stack by separating one concern at a time. The warehouse separated analytical from operational. The lake separated storage from compute. Snowflake separated the three commercially. Iceberg separated the table from any one engine. Each move reduced lock-in further. Architecture is rearrangement.&lt;/p&gt;
&lt;h3 id=&quot;what-each-generation-gave-up&quot;&gt;What each generation gave up&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/evolution/era-tradeoffs.svg&quot; alt=&quot;What each generation gained and gave up, era by era&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Every era moved &lt;em&gt;some&lt;/em&gt; capability up while pushing &lt;em&gt;some&lt;/em&gt; other one down. The warehouse won ACID and scan speed but gave up flexibility and cheapness. The lake won scale and openness but gave up transactions and interactivity. The lakehouse column is the first with no big giveaway — and that&#39;s not an accident. It&#39;s the cumulative payoff of fifty years of trade-off lessons: ACID came back from the warehouse era, scan speed kept the warehouse&#39;s strength at lake scale, schema flexibility survived through Iceberg&#39;s safe evolution, openness arrived as the organizing principle, and cost came down because storage commoditized.&lt;/p&gt;
&lt;p&gt;The lesson is not that the lakehouse is the final answer. It is that &lt;em&gt;the architecture that wins is the one that minimizes the giveaway&lt;/em&gt;. Future eras will introduce new constraints — real-time at scale, ML-native data, federated computation across silos — and the answer will preserve what we have here while pushing some new capability up.&lt;/p&gt;
&lt;h2 id=&quot;appendix-glossary-of-recurring-terms&quot;&gt;Appendix — glossary of recurring terms&lt;/h2&gt;
&lt;p&gt;A handful of terms recur throughout. Pinned here for reference.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ACID&lt;/strong&gt; — Atomicity, Consistency, Isolation, Durability. The contract a database makes about transactions: all-or-nothing writes, always-valid state, transactions don&#39;t see each other half-done, committed means permanent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OLTP / OLAP&lt;/strong&gt; — Online Transaction Processing (many small operations, low latency, single rows) versus Online Analytical Processing (fewer queries, each aggregating huge amounts of data).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MPP&lt;/strong&gt; — Massively Parallel Processing. Data partitioned across many nodes; a single query runs in parallel across all of them, and results combine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schema-on-write&lt;/strong&gt; — define the table first, then load data that fits; anything else is rejected. The opposite, schema-on-read, stores data as-is and applies structure at query time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Row group&lt;/strong&gt; — a horizontal slice of a Parquet file (typically 128MB–1GB) inside which each column is stored contiguously. What makes Parquet columnar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Predicate pushdown&lt;/strong&gt; — filtering data as close to storage as possible, using per-row-group min/max statistics to skip data that cannot match.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snapshot isolation&lt;/strong&gt; — each reader sees one consistent snapshot of a table from start to finish, regardless of concurrent writers. Iceberg gives this for free because old snapshots are kept.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-copy&lt;/strong&gt; — two processes or languages reading the same memory directly, without transformation. Possible when both agree on the exact byte layout; Arrow&#39;s reason for being.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vectorized execution&lt;/strong&gt; — processing data in batches rather than one row at a time, so the CPU&#39;s SIMD instructions act on many values at once. The execution model of every modern analytical engine, Dataglot included.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federation&lt;/strong&gt; — querying across multiple data sources from a single engine, without first moving the data into one place.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;appendix-the-reference-shelf&quot;&gt;Appendix — the reference shelf&lt;/h2&gt;
&lt;p&gt;Original sources for the engineering claims in this essay. Papers over blog posts; primary sources over commentary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Foundational papers&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Codd — &quot;A Relational Model of Data for Large Shared Data Banks&quot;, &lt;em&gt;Communications of the ACM&lt;/em&gt;, 1970. The paper that started relational databases.&lt;/li&gt;
&lt;li&gt;Ghemawat, Gobioff, Leung — &quot;The Google File System&quot;, SOSP 2003. The architecture that inspired HDFS.&lt;/li&gt;
&lt;li&gt;Dean, Ghemawat — &quot;MapReduce: Simplified Data Processing on Large Clusters&quot;, OSDI 2004.&lt;/li&gt;
&lt;li&gt;Stonebraker et al. — &quot;C-Store: A Column-oriented DBMS&quot;, VLDB 2005. The academic basis for Vertica and modern column stores.&lt;/li&gt;
&lt;li&gt;Melnik et al. — &quot;Dremel: Interactive Analysis of Web-Scale Datasets&quot;, VLDB 2010. Inspired Parquet and BigQuery.&lt;/li&gt;
&lt;li&gt;Zaharia et al. — &quot;Resilient Distributed Datasets&quot;, NSDI 2012. Spark&#39;s foundational paper.&lt;/li&gt;
&lt;li&gt;Armbrust, Ghodsi, Xin, Zaharia — &quot;Lakehouse Architecture&quot;, CIDR 2021. The paper that introduced &quot;lakehouse&quot; as a category.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Open specifications&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://parquet.apache.org&quot;&gt;Apache Parquet&lt;/a&gt; — project home and format spec.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://iceberg.apache.org/spec/&quot;&gt;Apache Iceberg table spec&lt;/a&gt; and the Iceberg REST catalog OpenAPI spec.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://arrow.apache.org/docs/format/&quot;&gt;Apache Arrow format specification&lt;/a&gt; — columnar memory layout, IPC, and Flight.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Engines and catalogs&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://datafusion.apache.org&quot;&gt;Apache DataFusion&lt;/a&gt; — the Rust query-execution framework Dataglot credits under the hood.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://spark.apache.org&quot;&gt;Apache Spark&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://duckdb.org&quot;&gt;DuckDB&lt;/a&gt; — neighboring engines referenced throughout.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/lakekeeper/lakekeeper&quot;&gt;Lakekeeper&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://polaris.apache.org&quot;&gt;Apache Polaris&lt;/a&gt; — open Iceberg REST catalog implementations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Books&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kleppmann — &lt;em&gt;Designing Data-Intensive Applications&lt;/em&gt; (O&#39;Reilly, 2017). The single best book on the architectural concepts in this essay.&lt;/li&gt;
&lt;li&gt;Kimball &amp;amp; Ross — &lt;em&gt;The Data Warehouse Toolkit&lt;/em&gt;; Inmon — &lt;em&gt;Building the Data Warehouse&lt;/em&gt;. The two original warehouse philosophies.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;We didn&#39;t invent a paradigm. We built cleanly on the one that won.&lt;/em&gt;&lt;/p&gt;
</description>
      </item>
      <item>
          <title>One Binary, No Drama: What a Rust-Native Engine Means for Your Ops</title>
          <pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://dataglot.ai/blog/one-binary-no-drama/</link>
          <guid>https://dataglot.ai/blog/one-binary-no-drama/</guid>
          <description xml:base="https://dataglot.ai/blog/one-binary-no-drama/">&lt;p&gt;Evaluating a federated query engine usually means evaluating a distributed system you&#39;ll have to babysit: a coordinator, a fleet of workers, a coordination service to keep them honest, a runtime with its own tuning discipline, and a wiki page of startup flags that someone on your team becomes the reluctant expert in.&lt;/p&gt;
&lt;p&gt;Dataglot is deliberately not that. It&#39;s a single static binary. This post is about what that means for the people who have to run it — which, if you&#39;re reading this, is probably you.&lt;/p&gt;
&lt;h2 id=&quot;one-artifact-everywhere&quot;&gt;One artifact, everywhere&lt;/h2&gt;
&lt;p&gt;The Dataglot you run on your laptop is the Dataglot you run in production. Pull it and go:&lt;/p&gt;
&lt;div class=&quot;code-tabs&quot; data-labels=&quot;Docker, Homebrew&quot;&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #59C2FF;&quot;&gt;docker&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; pull ghcr.io/dataglotai/dataglot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #59C2FF;&quot;&gt;brew&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; install dataglotai/tap/dataglot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There&#39;s no build step, no toolchain, no &quot;works in the container but not on the VM.&quot; The same artifact serves every role: a server speaking the PostgreSQL wire protocol, a one-shot CLI (&lt;code&gt;dataglot query&lt;/code&gt;) for scripts and CI checks, and an interactive REPL (&lt;code&gt;dataglot shell&lt;/code&gt;) — the last two run the full engine &lt;em&gt;in-process&lt;/em&gt;, so you can test a federated query or a masking policy without standing up a server at all.&lt;/p&gt;
&lt;p&gt;That has a quiet but real consequence for how teams adopt it: the data engineer trying an idea at 4pm and the platform team running it under SLOs are using the same binary with the same config format. Nothing gets &quot;translated for production.&quot;&lt;/p&gt;
&lt;h2 id=&quot;no-jvm-and-why-you-ll-notice&quot;&gt;No JVM, and why you&#39;ll notice&lt;/h2&gt;
&lt;p&gt;Dataglot has a hard rule: no JVM anywhere in the production runtime. If you&#39;ve operated JVM-based data infrastructure, you already know the list of things this deletes from your life:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No heap sizing.&lt;/strong&gt; There is no &lt;code&gt;-Xmx&lt;/code&gt; to get wrong, no ritual of setting the heap to 70% of the container and hoping the off-heap usage behaves. Memory usage is what the process actually needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No GC pause archaeology.&lt;/strong&gt; Latency spikes don&#39;t come with a side quest of correlating them against garbage-collection logs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No warm-up.&lt;/strong&gt; The engine starts in milliseconds and is immediately at full speed. That matters more than it sounds: fast starts make crash recovery boring, deploys unremarkable, and autoscaling actually usable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Small containers.&lt;/strong&gt; No JDK layer in the image. Smaller pulls, faster cold starts, less surface for your vulnerability scanner to complain about.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of this is exotic — it&#39;s just what you get when the entire engine compiles to native code. Dataglot builds on Apache DataFusion and Arrow, the proven Rust foundation for columnar SQL execution, and spends its own effort on what sits above: federation, governance, and the operational experience.&lt;/p&gt;
&lt;h2 id=&quot;scaling-up-without-changing-what-you-operate&quot;&gt;Scaling up without changing what you operate&lt;/h2&gt;
&lt;p&gt;Start on one node — for a lot of governed-federation workloads, one node is genuinely enough, because the heavy lifting is pushed down to the source databases anyway. &lt;code&gt;EXPLAIN FEDERATION&lt;/code&gt; will show you whole aggregations shipped to the systems that already own the data.&lt;/p&gt;
&lt;p&gt;When you do need distributed execution, the story stays calm: the same binary scales out to a scheduler-and-workers cluster, and high availability is coordinated &lt;strong&gt;through the object storage you already run&lt;/strong&gt; — no ZooKeeper, no etcd, no Redis quorum to patch, monitor, and page on. If you&#39;ve carried a pager for any of those, you know exactly how much noise that sentence deletes.&lt;/p&gt;
&lt;h2 id=&quot;fewer-moving-parts-is-a-governance-feature-too&quot;&gt;Fewer moving parts is a governance feature too&lt;/h2&gt;
&lt;p&gt;There&#39;s a compliance angle to all this that&#39;s easy to miss. Every extra component in a data platform — the policy sidecar, the UDF registry, the coordination service — is another thing an auditor asks about and another place enforcement can drift. In Dataglot, the engine that plans the query is the engine that enforces the policy, in one process, with the enforcement visible in the plan itself. A smaller system isn&#39;t just cheaper to run; it&#39;s easier to &lt;em&gt;prove things about&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;Five minutes, no compiler:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #BFBDB6; background-color: #0D1017;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #59C2FF;&quot;&gt;docker&lt;/span&gt;&lt;span style=&quot;color: #AAD94C;&quot;&gt; pull ghcr.io/dataglotai/dataglot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/docs/getting-started/&quot;&gt;quickstart&lt;/a&gt; takes you from that pull to a governed, cross-source query — and when it works, you&#39;ll have deployed the exact artifact you&#39;d take to production.&lt;/p&gt;
</description>
      </item>
    </channel>
</rss>
