<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Datamake blog</title>
    <subtitle>Notes on building composable data products with SQL, DuckDB, and Parquet.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://datamake.dev/blog/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://datamake.dev/blog"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-30T00:00:00+00:00</updated>
    <id>https://datamake.dev/blog/atom.xml</id>
    <entry xml:lang="en">
        <title>The modern data stack is fundamentally broken</title>
        <published>2026-07-30T00:00:00+00:00</published>
        <updated>2026-07-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            Scotty Pate
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://datamake.dev/blog/the-modern-data-stack-is-fundamentally-broken/"/>
        <id>https://datamake.dev/blog/the-modern-data-stack-is-fundamentally-broken/</id>
        
        <content type="html" xml:base="https://datamake.dev/blog/the-modern-data-stack-is-fundamentally-broken/">&lt;p&gt;Here&#x27;s a fun exercise. Count the purchase orders between &quot;we have data&quot; and
&quot;someone answered a question with it&quot; at a company running the modern data
stack.&lt;&#x2F;p&gt;
&lt;p&gt;You need an ingestion vendor to copy data out of your SaaS tools. You need a
cloud warehouse to put it in. You need a hosted transformation platform to
turn the raw copies into something usable, and an orchestrator to run it all
on a schedule. That&#x27;s four vendors, four procurement cycles, four onboarding
calls with a customer success manager — each one starting at five figures a
year, and that&#x27;s the &lt;em&gt;entry&lt;&#x2F;em&gt; price, before usage-based billing finds its
stride.&lt;&#x2F;p&gt;
&lt;p&gt;And here&#x27;s the part that should make you angry: at the end of all that, you
still haven&#x27;t shipped anything. You&#x27;ve built a &lt;em&gt;capability&lt;&#x2F;em&gt;. The stack is up,
the DAG is green, the invoices are recurring — and the actual thing someone
wanted, a trustworthy answer served to a dashboard or an app, is still a
ticket in the central data team&#x27;s queue.&lt;&#x2F;p&gt;
&lt;p&gt;Worse: every problem you had before the stack, you still have. Nobody agrees
on what &quot;revenue&quot; means. The dashboard broke because someone renamed a
column. The question that started this whole journey is three sprints deep
in a backlog. You didn&#x27;t buy solutions to those problems. You only bought a more
expensive place for them to live.&lt;&#x2F;p&gt;
&lt;p&gt;Then the second wave of vendors shows up to sell you solutions to the
problems the first wave created. A data observability tool, because nobody
can tell when a pipeline silently breaks. A data catalog, because nobody
knows what any of the 4,000 tables are for. A reverse-ETL tool, because after
paying to move data &lt;em&gt;into&lt;&#x2F;em&gt; the warehouse you now need to pay to move it back
&lt;em&gt;out&lt;&#x2F;em&gt;. Each of these is a real product solving a real problem, but the
problem is downstream of an architectural choice nobody remembers making.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;everything-software-learned-not-to-do-sold-back-to-you-as-architecture&quot;&gt;Everything software learned not to do, sold back to you as architecture&lt;&#x2F;h2&gt;
&lt;p&gt;Twenty years ago, software worked the way data works now. There was a
central IT team. You filed a ticket to get a server. Applications were
monoliths deployed by an ops group that didn&#x27;t write them, on a schedule
measured in quarters, and the people who understood the code and the people
who ran it in production were different people who communicated by blame.&lt;&#x2F;p&gt;
&lt;p&gt;Software didn&#x27;t fix that by buying better ticketing systems. It changed the
shape of ownership. Monoliths broke into modules and services with explicit
interfaces. &quot;You build it, you run it&quot; replaced the wall between dev and
ops. The central team stopped being a gatekeeper that did everyone&#x27;s work
and became a platform team that paved roads for others to drive on. Nobody
walked it back, because it worked.&lt;&#x2F;p&gt;
&lt;p&gt;Data is the last department still running the old playbook — and the modern
data stack didn&#x27;t retire it, it &lt;em&gt;renovated&lt;&#x2F;em&gt; it. A central team, a shared
monolith, a ticket queue, and a release process everyone routes around. And
the monolith at the center is worse than an organizational throwback; it&#x27;s a
technical one. Look at what the warehouse actually is, in software terms:
one global namespace of shared mutable state, where every consumer couples
directly to whatever internals are convenient, integration happens by
reading someone else&#x27;s tables, and changes ship with no version bump.
Global state. Depending on internals. Integration through a shared
database. Breaking changes without versions. Every one of those is a named
antipattern that fails code review in software. Stacked together, in data,
they&#x27;re the reference architecture.&lt;&#x2F;p&gt;
&lt;p&gt;So the breakage isn&#x27;t bad luck, it&#x27;s destiny. In the warehouse, &lt;strong&gt;every
table is reachable&lt;&#x2F;strong&gt;, so every dashboard, notebook, and ML job wires itself
to whatever layer is convenient — staging, intermediate, mart — and none of
those dependencies are declared anywhere. Your &quot;use case&quot; is a fuzzy region
of a spaghetti DAG. No table can tell you which use case it exists for, what
it promises, or whether it&#x27;s safe to delete. Every column you ship might be
load-bearing for a dashboard you&#x27;ve never heard of, so when someone renames
it, there&#x27;s no deprecation notice — it just breaks on a Tuesday, and the
postmortem is a Slack thread. Ownership goes diffuse, every change starts
with archaeology, and development slows to the speed of fear, with a central
team holding it together through tribal knowledge and human toil. That&#x27;s
what the five figures × N vendors actually buys: the organizational pattern
software spent two decades escaping, implemented on top of the technical
patterns software spent two decades banning, with a subscription ring of
tools to make living inside it more comfortable.&lt;&#x2F;p&gt;
&lt;p&gt;A pipeline doesn&#x27;t fix this, because a pipeline has no edges. Where does it
start? Where does it end? What does it promise? Who is allowed to use it?
Those answers live in someone&#x27;s head, a wiki page, and three Slack threads.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-way-out-is-not-another-vendor&quot;&gt;The way out is not another vendor&lt;&#x2F;h2&gt;
&lt;p&gt;If the diagnosis is &quot;the monolith has no boundaries,&quot; the fix isn&#x27;t a fifth
subscription that monitors the boundaries you don&#x27;t have. The fix is the
same one software found: a unit of ownership with private internals, an
explicit versioned interface, and a name on it. Data has that unit now —
it&#x27;s called a composable data product, and we wrote up exactly &lt;a href=&quot;https:&#x2F;&#x2F;datamake.dev&#x2F;blog&#x2F;wtf-is-a-composable-data-product&#x2F;&quot;&gt;what it
is&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The part worth stressing: it&#x27;s not a rip-and-replace. A composable data
product is &lt;strong&gt;compatible with the modern data stack, not a competitor to
it&lt;&#x2F;strong&gt;. Your warehouse doesn&#x27;t disappear; it becomes one input among others.
The stack keeps doing what it&#x27;s genuinely good at — one shared model,
operated by one team — and the use cases that never needed all that get
edges, contracts, and owners instead of a spot in the queue.&lt;&#x2F;p&gt;
&lt;p&gt;Software made this turn twenty years ago and never looked back. Data&#x27;s turn
is overdue.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>WTF is a composable data product?</title>
        <published>2026-07-24T00:00:00+00:00</published>
        <updated>2026-07-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            Scotty Pate
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://datamake.dev/blog/wtf-is-a-composable-data-product/"/>
        <id>https://datamake.dev/blog/wtf-is-a-composable-data-product/</id>
        
        <content type="html" xml:base="https://datamake.dev/blog/wtf-is-a-composable-data-product/">&lt;p&gt;Data products are like sex in high school: everyone is talking about it,
everyone assumes everyone else is doing it, and almost nobody is doing it
well. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;danariely&#x2F;status&#x2F;287952257926971392&quot;&gt;Dan Ariely made this joke&lt;&#x2F;a&gt;
about big data in 2013 — a decade on, we&#x27;ve only had to change the noun.)
Every vendor deck, product manager, and data executive of the last five
years has recited &quot;treat your data like a product&quot;. I&#x27;ve been a data
developer for fifteen years, so I&#x27;ve seen what actually lives behind that
slide: a spaghetti dependency graph that would embarrass its owners, if
anyone could figure out who the owners were.&lt;&#x2F;p&gt;
&lt;p&gt;The tell is the word itself. A &lt;em&gt;product&lt;&#x2F;em&gt; implies a boundary: something you
can ship, version, own, and point at. A schema in a shared warehouse is
not that. A dbt project is not that. A dashboard is definitely not that.&lt;&#x2F;p&gt;
&lt;p&gt;This post is about the unit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-in-one-paragraph&quot;&gt;The problem, in one paragraph&lt;&#x2F;h2&gt;
&lt;p&gt;In a shared warehouse, every table is reachable, so every dashboard,
notebook, and ML job wires itself to whatever layer is convenient. None of
those dependencies are declared anywhere. The producer of the data has no
idea you started using one of their tables as input to your real-time data
application. Your &quot;use case&quot; is a fuzzy region of a spaghetti DAG with no
owner, no promises, and no safe way to change. A pipeline doesn&#x27;t fix this,
because a pipeline has no edges: where does it start, where does it end,
what does it promise, who is allowed to use it? If you want the full
crucifixion — the vendor bill, the DevOps history lesson, the antipattern
bingo — that&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;datamake.dev&#x2F;blog&#x2F;the-modern-data-stack-is-fundamentally-broken&#x2F;&quot;&gt;its own
post&lt;&#x2F;a&gt;. Here, let&#x27;s just
fix it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-unit-a-cell&quot;&gt;The unit: a cell&lt;&#x2F;h2&gt;
&lt;p&gt;Software solved this exact problem decades ago with the module: private
internals, a small public interface, a version number, an owner. A
composable data product — we call it a &lt;strong&gt;cell&lt;&#x2F;strong&gt; — applies that to data. It
bundles four things that normally drift apart into one versioned,
deployable directory:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Logic&lt;&#x2F;strong&gt; — the SQL transforms, run in order, producing one atomic
snapshot.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Output&lt;&#x2F;strong&gt; — not &quot;a table you hope is right,&quot; but a snapshot that is
machine-verified against a declared shape on every build. Declared column
missing? Declared grain not actually unique in the data? The build
&lt;strong&gt;fails&lt;&#x2F;strong&gt;. Not a warning, not a test someone forgot to run — a failure.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Interface&lt;&#x2F;strong&gt; — an explicit export list, like &lt;code&gt;pub&lt;&#x2F;code&gt; in a programming
language. It inverts the warehouse default: everything is &lt;strong&gt;private unless
declared&lt;&#x2F;strong&gt;. Internals can churn freely; non-exported tables don&#x27;t just
lack documentation, they have no route at all.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Access&lt;&#x2F;strong&gt; — who can read the exports, declared in the same file, enforced
default-deny at the serving API.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The mental model is a software module for data. Inside: source reads,
scratch tables, intermediate state — all private, all owned by one clearly
named use case. Outside: a small, versioned public surface that &lt;em&gt;is&lt;&#x2F;em&gt; the
written-down requirements. The implicit dependencies the warehouse bakes in
become explicit declarations a producer can see and refuse.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-composable&quot;&gt;Why &quot;composable&quot;&lt;&#x2F;h2&gt;
&lt;p&gt;Because cells have explicit, versioned interfaces, they build on each other
the way code libraries do. A cell declares another cell&#x27;s export as a
source, by name and version, without a central team brokering the handoff.
A breaking change ships as a new major version served &lt;em&gt;alongside&lt;&#x2F;em&gt; the old
one — &lt;code&gt;orders@1&lt;&#x2F;code&gt; and &lt;code&gt;orders@2&lt;&#x2F;code&gt; at the same time — so consumers migrate on
their own clock, not yours. You get a graph of small products, each with a
stable public surface, private guts, and an owner, instead of one warehouse
where everything depends on everything and nobody knows how.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compatible-with-your-stack-not-a-competitor&quot;&gt;Compatible with your stack, not a competitor&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s the part people get wrong: a composable data product does not ask
you to rip anything out.&lt;&#x2F;p&gt;
&lt;p&gt;If you run a warehouse, keep it. It&#x27;s genuinely good at what it was built
for — one shared model, operated by one team — and a cell treats it as
&lt;strong&gt;one input among others&lt;&#x2F;strong&gt;: a cell can read warehouse tables, lake files,
and other cells&#x27; exports in the same breath. Your ingestion vendor keeps
landing data. Your dbt project keeps building the shared model. What
changes is what happens at the &lt;em&gt;edge&lt;&#x2F;em&gt;, where a specific use case meets its
consumers. Instead of pointing a dashboard at a mart table and praying,
you draw a boundary: these transforms, this contract, this versioned API,
this owner.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not a semantic layer either. A graph of independently-authored
contracts is not automatically one coherent data model. It&#x27;s a serving
boundary. The warehouse answers &quot;what does the organization know?&quot; A cell
answers &quot;what does &lt;em&gt;this use case&lt;&#x2F;em&gt; promise, to whom, at what version?&quot;
Those are different questions, and you can answer the second one without
re-litigating the first. For the use cases that never needed the
central stack at all, a cell is the escape hatch: it runs perfectly well
against Parquet on object storage with no warehouse in sight.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-looks-like-in-practice&quot;&gt;What this looks like in practice&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scalecraft-dev&#x2F;datamake&quot;&gt;Datamake&lt;&#x2F;a&gt; is an open-source
build system for exactly this unit. A cell is plain SQL plus one file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ell&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ransforms&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ql&#x2F;stg_orders.sql&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ql&#x2F;orders_daily.sql&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nterface&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rders_daily&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2.1.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rain&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rder_date&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;egion&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;chema&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rder_date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ate&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;egion&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;tring&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;evenue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ecimal&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Three commands take that from nothing to a versioned, contract-checked REST
API:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; datamk&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; init&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; orders&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; orders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; datamk&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; atomic snapshot, verified against the interface&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-function&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; datamk&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; serve&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; REST + OpenAPI on :8080&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s one Rust binary with an embedded DuckDB engine. Storage is Parquet,
the catalog is DuckLake — open formats end to end, so your data is never
held hostage. No cluster to stand up, no orchestration platform, no
procurement cycle. Apache-2.0, zero dollars, and the whole thing runs on
your laptop before lunch.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s the unit. Not a platform, not a mesh, not a philosophy — a
directory you can build, verify, version, and serve, that plugs into the
stack you already have.&lt;&#x2F;p&gt;
&lt;p&gt;For the deeper reasoning — diagrams included — read the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scalecraft-dev&#x2F;datamake&#x2F;blob&#x2F;main&#x2F;docs&#x2F;concepts&#x2F;composable-data-products.md&quot;&gt;concept
doc&lt;&#x2F;a&gt;.
Or skip the reading and run &lt;code&gt;datamk init&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
