<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://talkingschema.ai/blog/</id>
    <title>TalkingSchema Blog</title>
    <updated>2026-03-24T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://talkingschema.ai/blog/"/>
    <subtitle>Education, tutorials, and insights on AI-assisted database design</subtitle>
    <icon>https://talkingschema.ai/blog/img/favicon.svg</icon>
    <rights>Copyright © 2026 TalkingSchema</rights>
    <entry>
        <title type="html"><![CDATA[Kimball vs Inmon vs Data Vault 2.0: Choose Like an Architect, Not a Fanboy]]></title>
        <id>https://talkingschema.ai/blog/compare-inmon-kimball-datavault</id>
        <link href="https://talkingschema.ai/blog/compare-inmon-kimball-datavault"/>
        <updated>2026-03-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This article isn't about 'Which one is best?', but which one suits for your constraints: your people, your timelines, your source chaos, your compliance burden, your platform, and the fact that your organization will absolutely change its mind mid-quarter.]]></summary>
        <content type="html"><![CDATA[<p>If you've spent more than five minutes in data warehousing, you've seen it:</p>
<ul>
<li>Someone says "Kimball is dead, cloud fixes everything."</li>
<li>Someone else says "Inmon is the only serious enterprise architecture."</li>
<li>A third person slides in with "Data Vault 2.0 is the future—just add Hubs, Links, Satellites and boom: audit-ready agility."</li>
</ul>
<p>And then… nothing gets built for six weeks. Everyone shows up with a favorite methodology, a few conference slides in their head, and one dangerous sentence: "We should standardize on <em>the</em> right approach."</p>
<p>Here's my promise: this post will help you pick an approach the way an architect picks a structure—not like a sports fan picking a jersey .</p>
<p>Kimball, Inmon, and Data Vault 2.0 are not three rival religions. They are three different answers to one architectural question:</p>
<p><strong>Where do I want the pain to live?</strong></p>
<ul>
<li>In the reporting layer, so business users get answers fast?</li>
<li>In the enterprise integration layer, so the company has one governed backbone?</li>
<li>In a historized core, so source chaos and audit pressure stop breaking the model?</li>
</ul>
<p>The “methods” differ mostly in <strong>which job they optimize first</strong>.</p>
<p><strong>At the highest level, every analytical data platform is trying to do three jobs:</strong></p>
<ol>
<li><strong>Capture</strong> what happened (reliably and repeatably).</li>
<li><strong>Integrate</strong> it into shared meaning (so “customer” isn’t five different creatures).</li>
<li><strong>Serve</strong> it to humans and machines (fast, consistent, explainable).</li>
</ol>
<p><strong>If you only remember one thing, make it this:</strong></p>
<blockquote>
<p><strong>These are not three competing “database shapes.”</strong><br>
<!-- -->They’re three different answers to: <em>“Where do we put integration, and when do we pay for it?”</em></p>
</blockquote>
<p>That’s why the debates get heated: teams are arguing about <strong>when</strong> to do hard work, not whether the hard work exists.</p>
<p>Before arguing about modeling philosophy, you need to understand the reality you're dealing with. That's what we invented TalkingSchema for, to explore the mess - which system owns customer identity, which system owns money, which table lies by omission, and where the business keeps asking questions the source systems were never designed to answer.</p>
<p>I’ll show you what that looks like, not from a whiteboard in a vacuum, but from source systems outward.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="the-source-system-reality-i-start-with">The source-system reality I start with<a href="https://talkingschema.ai/blog/compare-inmon-kimball-datavault#the-source-system-reality-i-start-with" class="hash-link" aria-label="Direct link to The source-system reality I start with" title="Direct link to The source-system reality I start with">​</a></h2>
<p>Here’s the source schema I mapped in TalkingSchema before touching any architectural decision. I recommend spending a moment with the ERD, and read the DBML notes. Understand the actual mess we’re designing for.</p>
<p>Imagine I'm building analytics for a mid-market commerce company. Nothing exotic. Just enough complexity to hurt.</p>
<p>Customer identity lives in <code>crm.customers</code>. Orders live in <code>sales.orders</code> and <code>sales.order_items</code>. Payments live in <code>billing.payments</code>. Shipments live in <code>fulfillment.shipments</code>. Inventory snapshots live in <code>inventory.stock_snapshots</code>. Marketing insists promo logic matters, so now we also have <code>marketing.promotions</code> and <code>marketing.order_promotions</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="source-schema">Source schema<a href="https://talkingschema.ai/blog/compare-inmon-kimball-datavault#source-schema" class="hash-link" aria-label="Direct link to Source schema" title="Direct link to Source schema">​</a></h2>
<div class="ts-thread-embed"><div class="ts-thread-embed-toolbar"><span class="ts-thread-embed-toolbar-title">Source Schema — E-commerce OLTP</span><div class="ts-thread-embed-toolbar-actions"><button class="ts-embed-btn" title="Expand schema"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 2h4v4M6 14H2v-4M14 10v4h-4M2 6V2h4"></path></svg>Expand</button></div></div><iframe src="https://talkingschema.ai/public/908fee4d-2567-4772-beed-3f695696daed" title="Source Schema — E-commerce OLTP" style="height:640px" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox" allowfullscreen=""></iframe><div class="ts-thread-embed-label"><a href="https://talkingschema.ai/public/908fee4d-2567-4772-beed-3f695696daed" target="_blank" rel="noopener noreferrer">Open full screen ↗</a></div></div>
<p>This is where methodology debates should begin: with the actual systems. Not with the end-state diagram people want to show at a meetup.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="three-methodologies-one-same-reality">Three methodologies, one same reality<a href="https://talkingschema.ai/blog/compare-inmon-kimball-datavault#three-methodologies-one-same-reality" class="hash-link" aria-label="Direct link to Three methodologies, one same reality" title="Direct link to Three methodologies, one same reality">​</a></h2>
<p>Now comes the part people usually overcomplicate.</p>
<p>We're still modeling the same business. Customers buy products. Orders create revenue. Payments settle money. Shipments move goods. Inventory changes over time.</p>
<p>What changes is <strong>which question I optimize first</strong>.</p>
<h4 class="anchor anchorWithStickyNavbar_JmGV" id="kimball-make-the-business-question-easy">Kimball: “Make the business question easy”<a href="https://talkingschema.ai/blog/compare-inmon-kimball-datavault#kimball-make-the-business-question-easy" class="hash-link" aria-label="Direct link to Kimball: “Make the business question easy”" title="Direct link to Kimball: “Make the business question easy”">​</a></h4>
<h4 class="anchor anchorWithStickyNavbar_JmGV" id="inmon-integrate-the-enterprise-before-you-decorate-it">Inmon: “Integrate the enterprise before you decorate it”<a href="https://talkingschema.ai/blog/compare-inmon-kimball-datavault#inmon-integrate-the-enterprise-before-you-decorate-it" class="hash-link" aria-label="Direct link to Inmon: “Integrate the enterprise before you decorate it”" title="Direct link to Inmon: “Integrate the enterprise before you decorate it”">​</a></h4>
<h4 class="anchor anchorWithStickyNavbar_JmGV" id="data-vault-20-assume-change-is-the-normal-state">Data Vault 2.0: “Assume change is the normal state”<a href="https://talkingschema.ai/blog/compare-inmon-kimball-datavault#data-vault-20-assume-change-is-the-normal-state" class="hash-link" aria-label="Direct link to Data Vault 2.0: “Assume change is the normal state”" title="Direct link to Data Vault 2.0: “Assume change is the normal state”">​</a></h4>
<p>Let's dive deep on each;</p>
<div class="ts-dtabs"><div class="ts-dtabs-section-header"><span class="ts-dtabs-section-label">Continue reading</span><p class="ts-dtabs-section-title">Architecture Deep Dives</p></div><div class="ts-dtabs-triggers"><button class="ts-dtabs-trigger-card" style="--ts-card-accent:#d97706" aria-expanded="false"><span class="ts-dtabs-trigger-tag">Kimball</span><p class="ts-dtabs-trigger-title">Kimball Dimensional Modeling</p><p class="ts-dtabs-trigger-desc">Fact tables, conformed dimensions, and the bus architecture — built incrementally and consumed directly by BI tools. Star schema applied to our e-commerce source.</p><span class="ts-dtabs-trigger-cta">Read deep dive<svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="transform:rotate(0deg);transition:transform 0.2s ease;flex-shrink:0"><path d="M4 6l4 4 4-4"></path></svg></span></button><button class="ts-dtabs-trigger-card" style="--ts-card-accent:#48a179" aria-expanded="false"><span class="ts-dtabs-trigger-tag">Inmon</span><p class="ts-dtabs-trigger-title">Bill Inmon's Information Factory</p><p class="ts-dtabs-trigger-desc">Build the enterprise DW layer first: integrated, non-volatile, time-variant. We walk through the full CIF schema for our e-commerce source.</p><span class="ts-dtabs-trigger-cta">Read deep dive<svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="transform:rotate(0deg);transition:transform 0.2s ease;flex-shrink:0"><path d="M4 6l4 4 4-4"></path></svg></span></button><button class="ts-dtabs-trigger-card" style="--ts-card-accent:#7c3aed" aria-expanded="false"><span class="ts-dtabs-trigger-tag">Data Vault 2.0</span><p class="ts-dtabs-trigger-title">Data Vault 2.0 Ambitious Infra</p><p class="ts-dtabs-trigger-desc">Hubs, Links, Satellites — a historized, audit-ready raw vault that survives source system churn. We build the full DV2 model and show the consumption layer on top.</p><span class="ts-dtabs-trigger-cta">Read deep dive<svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="transform:rotate(0deg);transition:transform 0.2s ease;flex-shrink:0"><path d="M4 6l4 4 4-4"></path></svg></span></button><button class="ts-dtabs-trigger-card" style="--ts-card-accent:#0891b2" aria-expanded="false"><span class="ts-dtabs-trigger-tag">Data Marts</span><p class="ts-dtabs-trigger-title">Facts &amp; Conformed Dimensions</p><p class="ts-dtabs-trigger-desc">How Inmon and Data Vault cores both feed the same dimensional marts. Sales, finance, fulfillment, inventory, customer, and ops marts — built as a conformed bus.</p><span class="ts-dtabs-trigger-cta">Read deep dive<svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="transform:rotate(0deg);transition:transform 0.2s ease;flex-shrink:0"><path d="M4 6l4 4 4-4"></path></svg></span></button><button class="ts-dtabs-trigger-card" style="--ts-card-accent:#64748b" aria-expanded="false"><span class="ts-dtabs-trigger-tag">Conclusion</span><p class="ts-dtabs-trigger-title">Architect's Decision Framework</p><p class="ts-dtabs-trigger-desc">Three myths debunked, five decision questions answered. A practical framework for choosing between Kimball, Inmon, and Data Vault — or combining all three.</p><span class="ts-dtabs-trigger-cta">Read deep dive<svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="transform:rotate(0deg);transition:transform 0.2s ease;flex-shrink:0"><path d="M4 6l4 4 4-4"></path></svg></span></button></div><div class="ts-dtabs-panel" style="display:none" aria-hidden="true"></div><div class="ts-dtabs-panel" style="display:none" aria-hidden="true"></div><div class="ts-dtabs-panel" style="display:none" aria-hidden="true"></div><div class="ts-dtabs-panel" style="display:none" aria-hidden="true"></div><div class="ts-dtabs-panel" style="display:none" aria-hidden="true"></div></div>]]></content>
        <author>
            <name>Karan Patel</name>
            <uri>https://www.linkedin.com/in/karansql/</uri>
        </author>
        <category label="architecture choice" term="architecture choice"/>
        <category label="inmon vs kimball vs data vault" term="inmon vs kimball vs data vault"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sharing Your Database Schema with Anyone]]></title>
        <id>https://talkingschema.ai/blog/sharing-public-threads</id>
        <link href="https://talkingschema.ai/blog/sharing-public-threads"/>
        <updated>2026-03-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Public threads let you share a fully interactive schema diagram — no account required to view. Here's how they work and when to use them.]]></summary>
        <content type="html"><![CDATA[<p>Database schemas are collaborative artifacts. They're discussed in PR reviews, included in RFCs, pasted into architecture docs, and explained to stakeholders who've never written a line of SQL. But getting a non-engineer to open a migration file and understand it is asking a lot.</p>
<p><strong>Public threads</strong> solve this with a shareable link to a read-only, interactive version of your schema — no account, no installation, no friction.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="what-is-a-public-thread">What is a public thread?<a href="https://talkingschema.ai/blog/sharing-public-threads#what-is-a-public-thread" class="hash-link" aria-label="Direct link to What is a public thread?" title="Direct link to What is a public thread?">​</a></h2>
<p>Every thread in TalkingSchema has a canonical URL. By default, that URL requires authentication. When you make a thread public, it becomes accessible to anyone with the link — fully rendered, pannable, zoomable, and readable.</p>
<p>Viewers can:</p>
<ul>
<li>Browse the entire ERD on the canvas</li>
<li>Click into any table to see its fields, types, and constraints</li>
<li>Follow relationship lines between tables</li>
<li>See enum definitions</li>
</ul>
<p>Viewers <strong>cannot</strong> make any changes. The schema is read-only. There's no "edit" button, no chat input, no way to accidentally modify anything.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="how-to-create-a-public-link">How to create a public link<a href="https://talkingschema.ai/blog/sharing-public-threads#how-to-create-a-public-link" class="hash-link" aria-label="Direct link to How to create a public link" title="Direct link to How to create a public link">​</a></h2>
<ol>
<li>Open any thread in <a href="https://talkingschema.ai/app" target="_blank" rel="noopener noreferrer">TalkingSchema</a></li>
<li>Click the <strong>Share</strong> button in the top toolbar</li>
<li>Toggle <strong>Public access</strong> on</li>
<li>Copy the generated URL</li>
</ol>
<p>The link looks like:</p>
<div class="codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-text codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token plain">https://talkingschema.ai/public/{thread-id}</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can share it anywhere — a Slack message, a Notion page, a GitHub issue, a product spec. Anyone who opens it sees the current state of the schema.</p>
<div class="theme-admonition theme-admonition-tip admonition_WCGJ alert alert--success"><div class="admonitionHeading_GCBg"><span class="admonitionIcon_L39b"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_pbrs"><p>Public thread links are live. If you update the schema, the link always reflects the latest version — there's no need to regenerate it.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="embedding-a-schema-in-a-page">Embedding a schema in a page<a href="https://talkingschema.ai/blog/sharing-public-threads#embedding-a-schema-in-a-page" class="hash-link" aria-label="Direct link to Embedding a schema in a page" title="Direct link to Embedding a schema in a page">​</a></h2>
<p>Public threads also work as iframe embeds. This is useful for documentation pages, blog posts (like this one!), or internal wikis where you want the schema visible in context.</p>
<p>Here's an example of a live, embedded public thread — an e-commerce schema with orders, products, customers, and inventory tracking:</p>
<div class="ts-thread-embed"><div class="ts-thread-embed-toolbar"><span class="ts-thread-embed-toolbar-title">E-commerce Schema</span><div class="ts-thread-embed-toolbar-actions"><button class="ts-embed-btn" title="Expand schema"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 2h4v4M6 14H2v-4M14 10v4h-4M2 6V2h4"></path></svg>Expand</button></div></div><iframe src="https://www.qa-talkingschema.com/public/435fab3c-886c-47f2-a665-dcba58532f93" title="E-commerce Schema" style="height:640px" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox" allowfullscreen=""></iframe><div class="ts-thread-embed-label"><a href="https://www.qa-talkingschema.com/public/435fab3c-886c-47f2-a665-dcba58532f93" target="_blank" rel="noopener noreferrer">Open full screen ↗</a></div></div>
<p>To embed in your own MDX or HTML:</p>
<div class="language-html codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-html codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">iframe</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://talkingschema.ai/public/{your-thread-id}</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">100%</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">height</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">640</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag special-attr attr-name" style="color:#00a4db">style</span><span class="token tag special-attr attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag special-attr attr-value punctuation" style="color:#393A34">"</span><span class="token tag special-attr attr-value value css language-css property" style="color:#36acaa">border</span><span class="token tag special-attr attr-value value css language-css punctuation" style="color:#393A34">:</span><span class="token tag special-attr attr-value value css language-css" style="color:#e3116c"> none</span><span class="token tag special-attr attr-value value css language-css punctuation" style="color:#393A34">;</span><span class="token tag special-attr attr-value value css language-css" style="color:#e3116c"> </span><span class="token tag special-attr attr-value value css language-css property" style="color:#36acaa">border-radius</span><span class="token tag special-attr attr-value value css language-css punctuation" style="color:#393A34">:</span><span class="token tag special-attr attr-value value css language-css" style="color:#e3116c"> </span><span class="token tag special-attr attr-value value css language-css number" style="color:#36acaa">12</span><span class="token tag special-attr attr-value value css language-css unit" style="color:#e3116c">px</span><span class="token tag special-attr attr-value value css language-css punctuation" style="color:#393A34">;</span><span class="token tag special-attr attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">title</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">Schema diagram</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">sandbox</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">  </span><span class="token tag attr-name" style="color:#00a4db">allowfullscreen</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"></span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">iframe</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="good-uses-for-public-schema-links">Good uses for public schema links<a href="https://talkingschema.ai/blog/sharing-public-threads#good-uses-for-public-schema-links" class="hash-link" aria-label="Direct link to Good uses for public schema links" title="Direct link to Good uses for public schema links">​</a></h2>
<p><strong>In pull requests</strong> — link the relevant schema thread so reviewers can see the data model without having to read migration files. They can click through relationships, check foreign keys, and confirm field types all from the PR page.</p>
<p><strong>In architecture docs</strong> — embed the schema directly in your Notion, Confluence, or internal wiki page. The schema stays live; you don't need to update a screenshot every time a table changes.</p>
<p><strong>In onboarding materials</strong> — new engineers can explore the schema at their own pace. Tables are clickable, relationships are visual, and there's no risk of accidentally changing anything.</p>
<p><strong>With external stakeholders</strong> — designers, product managers, and clients can understand the data model without needing to learn SQL or get access to your database.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="privacy-and-access-control">Privacy and access control<a href="https://talkingschema.ai/blog/sharing-public-threads#privacy-and-access-control" class="hash-link" aria-label="Direct link to Privacy and access control" title="Direct link to Privacy and access control">​</a></h2>
<p>A few things worth knowing:</p>
<ul>
<li>Public links can be <strong>revoked at any time</strong> — toggle public access off and the link immediately stops working</li>
<li>The link doesn't expose your conversation history or any agent context, only the schema itself</li>
<li>Public threads are indexed by URL but not by any search engine or directory (no SEO crawling)</li>
</ul>
<hr>
<p>Public threads and shareable links are available on all plans. To try it, open any thread and hit <strong>Share</strong>.</p>]]></content>
        <author>
            <name>Mishall Afzal</name>
            <uri>https://www.linkedin.com/in/mishallafzal/</uri>
        </author>
        <category label="sharing" term="sharing"/>
        <category label="collaboration" term="collaboration"/>
        <category label="public-threads" term="public-threads"/>
        <category label="erd" term="erd"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[One Schema, Ten Formats: Understanding TalkingSchema's Export System]]></title>
        <id>https://talkingschema.ai/blog/schema-export-formats</id>
        <link href="https://talkingschema.ai/blog/schema-export-formats"/>
        <updated>2026-02-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Your schema is the source of truth. The format is just a choice — and you should be able to make it at any time.]]></summary>
        <content type="html"><![CDATA[<p>A common frustration in backend development: you've designed a schema in one context (a diagramming tool, a migration file, a Prisma schema), and now you need it in a different format for a different purpose. You end up maintaining multiple representations of the same model — and keeping them in sync manually.</p>
<p>TalkingSchema takes a different approach. <strong>The schema is defined once.</strong> Any export format is generated from that single source of truth, on demand, without touching the original.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="the-ten-formats">The ten formats<a href="https://talkingschema.ai/blog/schema-export-formats#the-ten-formats" class="hash-link" aria-label="Direct link to The ten formats" title="Direct link to The ten formats">​</a></h2>
<p>Here's a quick reference for when you'd reach for each one:</p>
<table><thead><tr><th>Format</th><th>Use case</th></tr></thead><tbody><tr><td><strong>PostgreSQL</strong></td><td>Direct DDL for Postgres, Supabase, Neon</td></tr><tr><td><strong>MySQL</strong></td><td>DDL for MySQL 8+ or PlanetScale</td></tr><tr><td><strong>SQLite</strong></td><td>Embedded/local databases, mobile apps</td></tr><tr><td><strong>DBML</strong></td><td>Database Markup Language — human-readable, shareable</td></tr><tr><td><strong>JSON</strong></td><td>Structured representation for tooling or APIs</td></tr><tr><td><strong>Prisma</strong></td><td>Node.js/TypeScript ORM for Vercel, Railway, etc.</td></tr><tr><td><strong>Drizzle</strong></td><td>TypeScript-first ORM with SQL-like syntax</td></tr><tr><td><strong>TypeScript + Zod</strong></td><td>Type-safe schema for frontend validation</td></tr><tr><td><strong>OpenAPI</strong></td><td>REST API specification with schema components</td></tr><tr><td><strong>GraphQL</strong></td><td>Type definitions for GraphQL servers</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="same-schema-different-outputs">Same schema, different outputs<a href="https://talkingschema.ai/blog/schema-export-formats#same-schema-different-outputs" class="hash-link" aria-label="Direct link to Same schema, different outputs" title="Direct link to Same schema, different outputs">​</a></h2>
<p>Here's a minimal example — a <code>users</code> table with an <code>email</code> and a <code>created_at</code> field — rendered in four different formats to show what the same model looks like across contexts.</p>
<p><strong>PostgreSQL:</strong></p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> users </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id         BIGSERIAL </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  email      </span><span class="token keyword" style="color:#00009f">TEXT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">UNIQUE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  created_at TIMESTAMPTZ </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DEFAULT</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Prisma:</strong></p>
<div class="language-prisma codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-prisma codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token plain">model User {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id        Int      @id @default(autoincrement())</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  email     String   @unique</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  createdAt DateTime @default(now())</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  @@map("users")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Drizzle:</strong></p>
<div class="language-typescript codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-typescript codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> pgTable</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> bigserial</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> text</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> timestamp </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"drizzle-orm/pg-core"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> users </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pgTable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"users"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">bigserial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> mode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"number"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">primaryKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">text</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"email"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">notNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">unique</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  createdAt</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">timestamp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"created_at"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> withTimezone</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">notNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">defaultNow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>TypeScript + Zod:</strong></p>
<div class="language-typescript codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-typescript codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> z </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"zod"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token maybe-class-name">UserSchema</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">object</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">number</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">positive</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">email</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  createdAt</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">coerce</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">date</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name maybe-class-name">User</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">infer</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">typeof</span><span class="token plain"> </span><span class="token maybe-class-name">UserSchema</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="dbml-the-shareable-format">DBML: the shareable format<a href="https://talkingschema.ai/blog/schema-export-formats#dbml-the-shareable-format" class="hash-link" aria-label="Direct link to DBML: the shareable format" title="Direct link to DBML: the shareable format">​</a></h2>
<p>DBML (Database Markup Language) deserves a special mention. Unlike SQL dialects, DBML is designed to be readable by non-engineers — you can paste it into a doc, a PR description, or a Slack message and it reads naturally:</p>
<div class="language-dbml codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-dbml codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token plain">Table users {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id         bigint     [pk, increment]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  email      text       [not null, unique]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  created_at timestamptz [not null, default: `now()`]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Table orders {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id         bigint [pk, increment]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  user_id    bigint [not null, ref: &gt; users.id]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  total_cents int   [not null]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  status     text   [not null, default: 'pending']</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>ref: &gt; users.id</code> notation makes the relationship direction explicit at a glance. DBML is also the format TalkingSchema uses internally — which means it's always up to date with whatever you've built in the canvas.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="when-to-export">When to export<a href="https://talkingschema.ai/blog/schema-export-formats#when-to-export" class="hash-link" aria-label="Direct link to When to export" title="Direct link to When to export">​</a></h2>
<p>There's no single right time to export. A few common workflows:</p>
<ul>
<li><strong>Start of a project</strong>: Design in TalkingSchema, export SQL to seed your migration tool.</li>
<li><strong>During a review</strong>: Export DBML to include in your PR description for reviewers who don't want to open a diagram.</li>
<li><strong>Onboarding a new service</strong>: Export Prisma or Drizzle to bootstrap a new TypeScript service against an existing schema.</li>
<li><strong>API documentation</strong>: Export OpenAPI to generate server stubs or client SDKs.</li>
<li><strong>Frontend validation</strong>: Export TypeScript + Zod to keep form validation aligned with your database constraints.</li>
</ul>
<p>The key property is that <strong>any export reflects the current state of the schema</strong> — not a stale snapshot from six months ago.</p>
<hr>
<p>All export formats are available from the Export button on any thread. If there's a format you need that isn't here yet, <a href="https://talkingschema.ai/app" target="_blank" rel="noopener noreferrer">let us know</a>.</p>]]></content>
        <author>
            <name>Karan Patel</name>
            <uri>https://www.linkedin.com/in/karansql/</uri>
        </author>
        <category label="export" term="export"/>
        <category label="sql" term="sql"/>
        <category label="prisma" term="prisma"/>
        <category label="drizzle" term="drizzle"/>
        <category label="typescript" term="typescript"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[5 Schema Design Patterns Every Developer Should Know]]></title>
        <id>https://talkingschema.ai/blog/schema-design-patterns</id>
        <link href="https://talkingschema.ai/blog/schema-design-patterns"/>
        <updated>2026-02-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[From simple one-to-many joins to slowly changing dimensions — the patterns that show up in every serious data model, and how to implement them.]]></summary>
        <content type="html"><![CDATA[<p>Schema design isn't just about getting data to persist. It's about modeling the <em>shape</em> of your domain — the things that exist, the relationships between them, and the constraints that keep it all consistent. A good schema makes queries fast, business logic obvious, and migrations safe. A bad one makes all three miserable.</p>
<p>These are five patterns that appear in almost every non-trivial system, with notes on when to reach for each one.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="1-polymorphic-associations-done-right">1. Polymorphic associations (done right)<a href="https://talkingschema.ai/blog/schema-design-patterns#1-polymorphic-associations-done-right" class="hash-link" aria-label="Direct link to 1. Polymorphic associations (done right)" title="Direct link to 1. Polymorphic associations (done right)">​</a></h2>
<p>The naive version of polymorphism — a <code>commentable_type</code> + <code>commentable_id</code> column pair — works until you need a foreign key or an index. Instead, use a <strong>union table</strong>:</p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">-- Each commentable entity gets its own join table</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> post_comments </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id         BIGSERIAL </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  post_id    </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> posts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">ON</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DELETE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">CASCADE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  comment_id </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> comments</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">ON</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DELETE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">CASCADE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">UNIQUE</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">post_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> comment_id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> photo_comments </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id         BIGSERIAL </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  photo_id   </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> photos</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">ON</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DELETE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">CASCADE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  comment_id </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> comments</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">ON</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DELETE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">CASCADE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">UNIQUE</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">photo_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> comment_id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You get real referential integrity, proper indexes, and queries that the query planner can reason about. The cost is more tables — which is almost always worth it.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="2-hierarchical-data-with-closure-tables">2. Hierarchical data with closure tables<a href="https://talkingschema.ai/blog/schema-design-patterns#2-hierarchical-data-with-closure-tables" class="hash-link" aria-label="Direct link to 2. Hierarchical data with closure tables" title="Direct link to 2. Hierarchical data with closure tables">​</a></h2>
<p>Self-referential <code>parent_id</code> columns are easy to write and brutal to query. Getting all descendants of a node requires a recursive CTE or application-level recursion. The <strong>closure table</strong> pattern pre-computes every ancestor-descendant relationship:</p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> categories </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id   BIGSERIAL </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name </span><span class="token keyword" style="color:#00009f">TEXT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">-- Every (ancestor, descendant) pair, including self-references (depth = 0)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> category_tree </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ancestor_id   </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> categories</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  descendant_id </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> categories</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  depth         </span><span class="token keyword" style="color:#00009f">INT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DEFAULT</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ancestor_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> descendant_id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Getting all descendants of category <code>42</code> becomes a simple join:</p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">.</span><span class="token operator" style="color:#393A34">*</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> categories c</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">JOIN</span><span class="token plain"> category_tree t </span><span class="token keyword" style="color:#00009f">ON</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">descendant_id</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ancestor_id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">42</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">depth </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The trade-off: writes are more expensive (you insert N rows per new node, where N is the depth of the tree), but reads are O(1) regardless of tree depth.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="3-audit-logs-with-event-sourcing">3. Audit logs with event sourcing<a href="https://talkingschema.ai/blog/schema-design-patterns#3-audit-logs-with-event-sourcing" class="hash-link" aria-label="Direct link to 3. Audit logs with event sourcing" title="Direct link to 3. Audit logs with event sourcing">​</a></h2>
<p>Instead of updating rows in place, <strong>append only</strong> and reconstruct state from history. This is particularly useful for financial systems, compliance requirements, or anything where you need to ask "what did this look like on March 3rd?"</p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> account_events </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id           BIGSERIAL </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  account_id   </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain">    </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> accounts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  event_type   </span><span class="token keyword" style="color:#00009f">TEXT</span><span class="token plain">      </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">-- 'created', 'credited', 'debited', 'closed'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  amount_cents </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">             </span><span class="token comment" style="color:#999988;font-style:italic">-- NULL for non-monetary events</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  occurred_at  TIMESTAMPTZ </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DEFAULT</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  metadata     JSONB</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">-- Current balance is a derived value, not stored</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">VIEW</span><span class="token plain"> account_balances </span><span class="token keyword" style="color:#00009f">AS</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  account_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">SUM</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">CASE</span><span class="token plain"> event_type</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">WHEN</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'credited'</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">THEN</span><span class="token plain"> amount_cents</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">WHEN</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'debited'</span><span class="token plain">  </span><span class="token keyword" style="color:#00009f">THEN</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">amount_cents</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">ELSE</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">END</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">AS</span><span class="token plain"> balance_cents</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> account_events</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">GROUP</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">BY</span><span class="token plain"> account_id</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The event log is the source of truth. The balance is a projection. You can replay history, add new projections later, and audit every state transition for free.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="4-soft-deletes-with-deleted_at">4. Soft deletes with <code>deleted_at</code><a href="https://talkingschema.ai/blog/schema-design-patterns#4-soft-deletes-with-deleted_at" class="hash-link" aria-label="Direct link to 4-soft-deletes-with-deleted_at" title="Direct link to 4-soft-deletes-with-deleted_at">​</a></h2>
<p>Rather than <code>DELETE</code>ing rows, set a <code>deleted_at</code> timestamp. Queries filter it out; the data stays recoverable.</p>
<table><thead><tr><th>Approach</th><th>Recovery</th><th>FK integrity</th><th>Query simplicity</th></tr></thead><tbody><tr><td>Hard delete</td><td>✗</td><td>Cascades automatically</td><td>Simple</td></tr><tr><td>Soft delete</td><td>✓</td><td>Must filter in every query</td><td>Requires discipline</td></tr><tr><td>Archive table</td><td>✓</td><td>Maintained</td><td>Moderate</td></tr></tbody></table>
<p>The catch with soft deletes is that <strong>every query must include the filter</strong> — easy to forget, especially in ORM-generated queries. A database view or row-level security policy can enforce it:</p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">-- All queries against this view automatically exclude soft-deleted rows</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">VIEW</span><span class="token plain"> active_users </span><span class="token keyword" style="color:#00009f">AS</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> users </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> deleted_at </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Reserve soft deletes for entities that users expect to be recoverable (posts, documents, records). Don't use them for join tables or events — those should be hard deleted or append-only, respectively.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="5-slowly-changing-dimensions-scd-type-2">5. Slowly changing dimensions (SCD Type 2)<a href="https://talkingschema.ai/blog/schema-design-patterns#5-slowly-changing-dimensions-scd-type-2" class="hash-link" aria-label="Direct link to 5. Slowly changing dimensions (SCD Type 2)" title="Direct link to 5. Slowly changing dimensions (SCD Type 2)">​</a></h2>
<p>When historical accuracy matters — for analytics, audits, or reporting — you need to track how data <em>changed over time</em>, not just what it is <em>now</em>. Type 2 SCDs do this by adding validity windows to every version of a record:</p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> product_prices </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id           BIGSERIAL </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  product_id   </span><span class="token keyword" style="color:#00009f">BIGINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> products</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  price_cents  </span><span class="token keyword" style="color:#00009f">INT</span><span class="token plain">    </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  currency     </span><span class="token keyword" style="color:#00009f">CHAR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DEFAULT</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'USD'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  valid_from   </span><span class="token keyword" style="color:#00009f">DATE</span><span class="token plain">   </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  valid_until  </span><span class="token keyword" style="color:#00009f">DATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">-- NULL means "current"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  is_current   </span><span class="token keyword" style="color:#00009f">BOOLEAN</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DEFAULT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">CONSTRAINT</span><span class="token plain"> one_current_price_per_product</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    EXCLUDE </span><span class="token keyword" style="color:#00009f">USING</span><span class="token plain"> GIST </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">product_id </span><span class="token keyword" style="color:#00009f">WITH</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">is_current </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To find the price on a specific date:</p>
<div class="language-sql codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-sql codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> price_cents</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> product_prices</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> product_id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> $</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> valid_from </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> $</span><span class="token number" style="color:#36acaa">2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">valid_until </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">OR</span><span class="token plain"> valid_until </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> $</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>EXCLUDE USING GIST</code> constraint ensures only one price is marked <code>is_current</code> per product, enforced at the database level.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="a-note-on-schema-evolution">A note on schema evolution<a href="https://talkingschema.ai/blog/schema-design-patterns#a-note-on-schema-evolution" class="hash-link" aria-label="Direct link to A note on schema evolution" title="Direct link to A note on schema evolution">​</a></h2>
<p>These patterns are a starting point, not a destination. Real schemas evolve — columns get added, tables split, constraints tighten. The patterns above are designed to make evolution <em>safer</em>: append-only events don't need migrations; closure tables can be rebuilt; SCD rows are never updated, only closed.</p>
<p>If you're designing a new schema from scratch, try describing the domain in plain language first. What are the <em>things</em>? What are the <em>relationships</em>? What constraints are <em>always</em> true? The code follows from the answers — not the other way around.</p>]]></content>
        <author>
            <name>TalkingSchema Team</name>
            <uri>https://talkingschema.ai</uri>
        </author>
        <category label="schema-design" term="schema-design"/>
        <category label="sql" term="sql"/>
        <category label="best-practices" term="best-practices"/>
        <category label="data-modeling" term="data-modeling"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI-First Database Design: Rethinking How We Build Data Models]]></title>
        <id>https://talkingschema.ai/blog/ai-first-database-design</id>
        <link href="https://talkingschema.ai/blog/ai-first-database-design"/>
        <updated>2026-01-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Natural language has always been how we think about data. Now it's how we build it too — here's what that actually changes.]]></summary>
        <content type="html"><![CDATA[<p>For decades, designing a database meant one of two things: writing SQL DDL by hand, or dragging boxes around a diagramming tool. Both approaches force you to think in the machine's language before you've finished thinking in your own.</p>
<p>TalkingSchema is built on a different premise: <strong>you should be able to describe your data model the way you'd explain it to a colleague</strong>, and get a working, exportable schema out the other side.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="the-gap-between-thinking-and-building">The gap between thinking and building<a href="https://talkingschema.ai/blog/ai-first-database-design#the-gap-between-thinking-and-building" class="hash-link" aria-label="Direct link to The gap between thinking and building" title="Direct link to The gap between thinking and building">​</a></h2>
<p>When you're designing a schema for a new feature, you usually start with something like:</p>
<blockquote>
<p><em>"We need to track orders. Each order belongs to a customer and can have multiple line items. Each line item references a product, and products belong to categories."</em></p>
</blockquote>
<p>That's a perfectly clear data model. But turning it into SQL requires a mental translation step — mapping nouns to tables, relationships to foreign keys, constraints to CHECK clauses. The design work is done in English; the implementation happens in a different language entirely.</p>
<p>This translation tax is low for experienced engineers, but it compounds across iterations. Every time requirements change, you re-enter DDL, re-sync your diagram, and hope nothing drifts.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="what-changes-with-a-conversational-approach">What changes with a conversational approach<a href="https://talkingschema.ai/blog/ai-first-database-design#what-changes-with-a-conversational-approach" class="hash-link" aria-label="Direct link to What changes with a conversational approach" title="Direct link to What changes with a conversational approach">​</a></h2>
<p>With TalkingSchema, the description <em>is</em> the schema. You type the same sentence you'd say to a colleague and the tool:</p>
<ol>
<li>Creates the tables (<code>orders</code>, <code>customers</code>, <code>line_items</code>, <code>products</code>, <code>categories</code>)</li>
<li>Infers the relationships (foreign keys with correct cardinality)</li>
<li>Suggests field types based on context</li>
<li>Draws the ERD — live, as you go</li>
</ol>
<p>The result is visible immediately on the canvas. You can zoom in, click any table to edit it, rename fields, add constraints, or keep prompting in plain language.</p>
<div class="codeBlockContainer_mQmQ theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_D5yF"><pre tabindex="0" class="prism-code language-text codeBlock_RMoD thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_AclH"><span class="token-line" style="color:#393A34"><span class="token plain">User: Add a discount field to line_items. It should be a percentage, nullable, max 100.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">TalkingSchema: Added `discount` (DECIMAL(5,2), nullable, CHECK discount &lt;= 100) to line_items.</span><br></span></code></pre><div class="buttonGroup_aaMX"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_z5j7" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_FoOz"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_L0B6"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="two-modes-for-two-kinds-of-thinking">Two modes for two kinds of thinking<a href="https://talkingschema.ai/blog/ai-first-database-design#two-modes-for-two-kinds-of-thinking" class="hash-link" aria-label="Direct link to Two modes for two kinds of thinking" title="Direct link to Two modes for two kinds of thinking">​</a></h2>
<p>Not every schema is the output of a single conversation. Sometimes you want the AI to make changes instantly — and sometimes you want to review a plan before anything gets applied.</p>
<p><strong>Draw mode</strong> applies changes directly as you describe them. It's fast, good for exploration, and ideal when you know roughly what you want.</p>
<p><strong>Plan mode</strong> lets the AI propose a set of changes for your review before anything is committed to the schema. It's better for complex restructures where you want to understand the impact before saying yes.</p>
<p>Both modes output the same schema — the difference is whether changes land immediately or after your approval.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="the-schema-stays-portable">The schema stays portable<a href="https://talkingschema.ai/blog/ai-first-database-design#the-schema-stays-portable" class="hash-link" aria-label="Direct link to The schema stays portable" title="Direct link to The schema stays portable">​</a></h2>
<p>At any point, you can export the full schema to SQL (PostgreSQL, MySQL, SQLite, and others), Prisma, Drizzle, DBML, JSON, OpenAPI, and more. The AI conversation is the <em>input</em> — your preferred format is the <em>output</em>.</p>
<blockquote>
<p>"The database schema is the single most important artifact in any software project. Getting it right early — and being able to iterate quickly — changes everything downstream."</p>
</blockquote>
<p>This is what we're optimizing for: making the iteration loop fast enough that getting the schema right early is actually possible.</p>
<h2 class="anchor anchorWithStickyNavbar_JmGV" id="getting-started">Getting started<a href="https://talkingschema.ai/blog/ai-first-database-design#getting-started" class="hash-link" aria-label="Direct link to Getting started" title="Direct link to Getting started">​</a></h2>
<p>If you haven't tried it yet, the quickest way in is to open a new thread and describe your first table in plain English. You don't need to install anything — it runs entirely in the browser.</p>
<ul>
<li><a href="https://talkingschema.ai/docs/getting-started/quick-start" target="_blank" rel="noopener noreferrer">Quick Start guide</a></li>
<li><a href="https://talkingschema.ai/docs/ai-copilot/draw-mode" target="_blank" rel="noopener noreferrer">How Draw mode works</a></li>
<li><a href="https://talkingschema.ai/docs/ai-copilot/prompting-tips" target="_blank" rel="noopener noreferrer">Prompting tips for better results</a></li>
</ul>]]></content>
        <author>
            <name>Karan Patel</name>
            <uri>https://www.linkedin.com/in/karansql/</uri>
        </author>
        <author>
            <name>Mishall Afzal</name>
            <uri>https://www.linkedin.com/in/mishallafzal/</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="database-design" term="database-design"/>
        <category label="getting-started" term="getting-started"/>
    </entry>
</feed>