<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://docs.foundrydb.com/blog</id>
    <title>FoundryDB Docs Blog</title>
    <updated>2026-04-07T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://docs.foundrydb.com/blog"/>
    <subtitle>FoundryDB Docs Blog</subtitle>
    <icon>https://docs.foundrydb.com/img/favicon.svg</icon>
    <entry>
        <title type="html"><![CDATA[Migrate from DigitalOcean Managed Databases to FoundryDB]]></title>
        <id>https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb</id>
        <link href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb"/>
        <updated>2026-04-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Upgrade from DigitalOcean to FoundryDB for more engines, AI features, and richer monitoring.]]></summary>
        <content type="html"><![CDATA[<p>DigitalOcean Managed Databases is a popular starting point for teams that want hosted PostgreSQL, MySQL, MongoDB, or Valkey without managing infrastructure. It does the basics well: provisioning, automated backups, and TLS. But as your data platform matures, the limitations become clear. Four engines, minimal monitoring, no AI-oriented features, no pipeline templates, and no way to export metrics to your own observability stack. FoundryDB offers seven engines, built-in AI presets, predictive autoscaling, database forking, and seven metrics export destinations, all on European infrastructure.</p>
<p>This guide covers migrating all three of the most common DigitalOcean database engines (PostgreSQL, MySQL, and MongoDB) to FoundryDB. Each section is self-contained, so you can follow just the one relevant to your stack or migrate multiple databases in parallel.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-migrate-from-digitalocean">Why Migrate from DigitalOcean?<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#why-migrate-from-digitalocean" class="hash-link" aria-label="Direct link to Why Migrate from DigitalOcean?" title="Direct link to Why Migrate from DigitalOcean?">​</a></h2>
<p>DigitalOcean's managed database service has served many teams as a reliable first step, but production workloads often demand more:</p>
<ul>
<li><strong>Four engines only.</strong> DigitalOcean offers PostgreSQL, MySQL, MongoDB, and Valkey. If you need Kafka for event streaming, OpenSearch for full-text search, or Babelfish for SQL Server wire compatibility, you need a separate provider.</li>
<li><strong>Basic monitoring.</strong> The DigitalOcean dashboard shows CPU, memory, disk, and connection metrics. There are no query-level analytics, no slow query breakdowns, no custom alerting thresholds, and no way to export metrics to Grafana, Datadog, or Prometheus.</li>
<li><strong>No AI features.</strong> There are no pgvector presets, no embedding pipeline templates, no AI-assisted query optimization, and no built-in support for RAG architectures.</li>
<li><strong>No database forking.</strong> Creating a copy of a production database for testing or analytics requires manual dump-and-restore. FoundryDB supports instant forking from any backup or point-in-time snapshot.</li>
<li><strong>No predictive autoscaling.</strong> DigitalOcean requires manual scaling decisions. You monitor metrics, decide when to resize, and trigger the operation yourself.</li>
<li><strong>Limited connection pooling.</strong> DigitalOcean offers basic built-in connection pooling for PostgreSQL but lacks the advanced query routing and read/write splitting that ProxySQL (MySQL) or PgBouncer (PostgreSQL) provide.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h2>
<p>For all migrations below, you need:</p>
<ul>
<li><strong>A FoundryDB account</strong> at <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">foundrydb.com</a></li>
<li><strong>The fdb CLI</strong> installed (<code>brew install foundrydb/tap/fdb</code> or download from the dashboard)</li>
<li>Access to your DigitalOcean database credentials (available in the DO dashboard under Databases &gt; Connection Details)</li>
</ul>
<p>Engine-specific tools:</p>
<ul>
<li><strong>PostgreSQL:</strong> <code>pg_dump</code> and <code>pg_restore</code> (included with any PostgreSQL client)</li>
<li><strong>MySQL:</strong> <code>mysqldump</code> and <code>mysql</code> client</li>
<li><strong>MongoDB:</strong> <code>mongodump</code> and <code>mongorestore</code> (included with MongoDB Database Tools)</li>
</ul>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="postgresql-migration">PostgreSQL Migration<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#postgresql-migration" class="hash-link" aria-label="Direct link to PostgreSQL Migration" title="Direct link to PostgreSQL Migration">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="export-from-digitalocean">Export from DigitalOcean<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#export-from-digitalocean" class="hash-link" aria-label="Direct link to Export from DigitalOcean" title="Direct link to Export from DigitalOcean">​</a></h3>
<p>Get your DigitalOcean PostgreSQL connection details from the dashboard, then run <code>pg_dump</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">pg_dump </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql://doadmin:YOUR_DO_PASSWORD@db-postgresql-sto1-12345-do-user.b.db.ondigitalocean.com:25060/defaultdb?sslmode=require"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--format</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">custom </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-owner </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-privileges </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--verbose</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-f</span><span class="token plain"> digitalocean-pg.dump</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 custom format produces a compressed binary dump that supports parallel restore and selective table import.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="create-on-foundrydb">Create on FoundryDB<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#create-on-foundrydb" class="hash-link" aria-label="Direct link to Create on FoundryDB" title="Direct link to Create on FoundryDB">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --database-type postgresql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">17</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --plan-name tier-2 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-size-gb </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> my-pg-db </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> se-sto1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Wait for the service to reach <code>Running</code> status:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb status my-pg-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="import">Import<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#import" class="hash-link" aria-label="Direct link to Import" title="Direct link to Import">​</a></h3>
<p>Retrieve your FoundryDB credentials and restore:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-pg-db </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--info</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">pg_restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--host</span><span class="token plain"> my-pg-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--port</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">5432</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--username</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--dbname</span><span class="token plain"> defaultdb </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-owner </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-privileges </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--jobs</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--verbose</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  digitalocean-pg.dump</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="verify">Verify<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#verify" class="hash-link" aria-label="Direct link to Verify" title="Direct link to Verify">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-pg-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Compare table counts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">count</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token operator" style="color:rgb(212, 212, 212)">*</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> information_schema</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token keyword" style="color:rgb(86, 156, 214)">tables</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> table_schema </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'public'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Check row counts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> schemaname</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> relname</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> n_live_tup</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> pg_stat_user_tables</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> n_live_tup </span><span class="token keyword" style="color:rgb(86, 156, 214)">DESC</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">LIMIT</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">20</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Verify extensions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> extname</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> extversion </span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> pg_extension</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="mysql-migration">MySQL Migration<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#mysql-migration" class="hash-link" aria-label="Direct link to MySQL Migration" title="Direct link to MySQL Migration">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="export-from-digitalocean-1">Export from DigitalOcean<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#export-from-digitalocean-1" class="hash-link" aria-label="Direct link to Export from DigitalOcean" title="Direct link to Export from DigitalOcean">​</a></h3>
<p>Get your DigitalOcean MySQL connection details, then dump:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysqldump </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-h</span><span class="token plain"> db-mysql-sto1-12345-do-user.b.db.ondigitalocean.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-P</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">25060</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> doadmin </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-pYOUR_DO_PASSWORD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --ssl-mode</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">REQUIRED </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --set-gtid-purged</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">OFF </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --single-transaction </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--routines</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--triggers</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-tablespaces </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  defaultdb </span><span class="token operator" style="color:rgb(212, 212, 212)">&gt;</span><span class="token plain"> digitalocean-mysql.sql</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>--single-transaction</code> flag ensures a consistent snapshot without locking tables. The <code>--set-gtid-purged=OFF</code> flag avoids GTID conflicts when importing into a fresh instance.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="create-on-foundrydb-1">Create on FoundryDB<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#create-on-foundrydb-1" class="hash-link" aria-label="Direct link to Create on FoundryDB" title="Direct link to Create on FoundryDB">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --database-type mysql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">8.4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --plan-name tier-2 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-size-gb </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> my-mysql-db </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> se-sto1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Wait for <code>Running</code> status:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb status my-mysql-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="import-1">Import<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#import-1" class="hash-link" aria-label="Direct link to Import" title="Direct link to Import">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-mysql-db </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--info</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-h</span><span class="token plain"> my-mysql-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-pYOUR_PASSWORD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --ssl-mode</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">REQUIRED </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  defaultdb </span><span class="token operator" style="color:rgb(212, 212, 212)">&lt;</span><span class="token plain"> digitalocean-mysql.sql</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="verify-1">Verify<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#verify-1" class="hash-link" aria-label="Direct link to Verify" title="Direct link to Verify">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-mysql-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Check tables</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">TABLES</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Verify row counts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> table_name</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> table_rows</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> information_schema</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token keyword" style="color:rgb(86, 156, 214)">tables</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> table_schema </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'defaultdb'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> table_rows </span><span class="token keyword" style="color:rgb(86, 156, 214)">DESC</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Check stored routines migrated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">PROCEDURE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">STATUS</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> Db </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'defaultdb'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">FUNCTION</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">STATUS</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> Db </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'defaultdb'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="mongodb-migration">MongoDB Migration<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#mongodb-migration" class="hash-link" aria-label="Direct link to MongoDB Migration" title="Direct link to MongoDB Migration">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="export-from-digitalocean-2">Export from DigitalOcean<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#export-from-digitalocean-2" class="hash-link" aria-label="Direct link to Export from DigitalOcean" title="Direct link to Export from DigitalOcean">​</a></h3>
<p>Get your DigitalOcean MongoDB connection string, then dump:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mongodump </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--uri</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"mongodb+srv://doadmin:YOUR_DO_PASSWORD@db-mongodb-sto1-12345.mongo.ondigitalocean.com/admin?authSource=admin&amp;tls=true"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--db</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">my_database </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--out</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">./digitalocean-mongo-dump</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This creates a directory with BSON files for each collection. For large databases, add <code>--gzip</code> to compress the output:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mongodump </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--uri</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"mongodb+srv://doadmin:YOUR_DO_PASSWORD@db-mongodb-sto1-12345.mongo.ondigitalocean.com/admin?authSource=admin&amp;tls=true"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--db</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">my_database </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--gzip</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--out</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">./digitalocean-mongo-dump</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="create-on-foundrydb-2">Create on FoundryDB<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#create-on-foundrydb-2" class="hash-link" aria-label="Direct link to Create on FoundryDB" title="Direct link to Create on FoundryDB">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --database-type mongodb </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">7.0</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --plan-name tier-2 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-size-gb </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> my-mongo-db </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> se-sto1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Wait for <code>Running</code> status:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb status my-mongo-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="import-2">Import<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#import-2" class="hash-link" aria-label="Direct link to Import" title="Direct link to Import">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-mongo-db </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--info</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">mongorestore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--uri</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"mongodb://app_user:YOUR_PASSWORD@my-mongo-db-abc123.db.foundrydb.com:27017/defaultdb?tls=true&amp;authSource=admin"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--nsFrom</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"my_database.*"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--nsTo</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"defaultdb.*"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  ./digitalocean-mongo-dump/my_database</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>If you used <code>--gzip</code> during the dump, add <code>--gzip</code> to the restore command as well. The <code>--nsFrom</code> and <code>--nsTo</code> flags remap the database name from your DigitalOcean source to <code>defaultdb</code> on FoundryDB.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="verify-2">Verify<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#verify-2" class="hash-link" aria-label="Direct link to Verify" title="Direct link to Verify">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-mongo-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">// List collections</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">show collections</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">// Check document counts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getCollectionNames</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">forEach</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token keyword" style="color:rgb(86, 156, 214)">function</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token parameter">c</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token function" style="color:rgb(220, 220, 170)">print</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">c </span><span class="token operator" style="color:rgb(212, 212, 212)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">": "</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">+</span><span class="token plain"> db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain">c</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">countDocuments</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">// Verify indexes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getCollectionNames</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">forEach</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token keyword" style="color:rgb(86, 156, 214)">function</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token parameter">c</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token function" style="color:rgb(220, 220, 170)">print</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">"--- "</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">+</span><span class="token plain"> c </span><span class="token operator" style="color:rgb(212, 212, 212)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">" ---"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token function" style="color:rgb(220, 220, 170)">printjson</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain">c</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getIndexes</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">// Test a query</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token property-access">users</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">find</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">limit</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token number" style="color:rgb(181, 206, 168)">5</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">pretty</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="updating-your-application">Updating Your Application<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#updating-your-application" class="hash-link" aria-label="Direct link to Updating Your Application" title="Direct link to Updating Your Application">​</a></h2>
<p>After importing data into FoundryDB, update your application's connection strings. The new format depends on the engine:</p>
<p><strong>PostgreSQL:</strong></p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">postgresql://app_user:PASSWORD@my-pg-db-abc123.db.foundrydb.com:5432/defaultdb?sslmode=require</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>MySQL:</strong></p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysql://app_user:PASSWORD@my-mysql-db-abc123.db.foundrydb.com:3306/defaultdb?ssl-mode=REQUIRED</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>MongoDB:</strong></p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mongodb://app_user:PASSWORD@my-mongo-db-abc123.db.foundrydb.com:27017/defaultdb?tls=true&amp;authSource=admin</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>For zero-downtime migrations on high-traffic applications, consider running both databases in parallel briefly: point your application at FoundryDB, monitor for errors, and decommission the DigitalOcean instance once you have confirmed stability.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-you-gain-after-migrating">What You Gain After Migrating<a href="https://docs.foundrydb.com/blog/migrate-from-digitalocean-managed-databases-to-foundrydb#what-you-gain-after-migrating" class="hash-link" aria-label="Direct link to What You Gain After Migrating" title="Direct link to What You Gain After Migrating">​</a></h2>
<p>Moving from DigitalOcean Managed Databases to FoundryDB gives you access to a significantly richer platform:</p>
<ul>
<li><strong>7 engines instead of 4.</strong> PostgreSQL, MySQL, MongoDB, Valkey, Kafka, OpenSearch, and Babelfish. Manage all of them from one CLI, one dashboard, one bill.</li>
<li><strong>AI-ready presets.</strong> Provision a PostgreSQL instance with pgvector pre-configured for embedding storage, or create a Kafka + PostgreSQL pipeline for RAG architectures, all from predefined presets.</li>
<li><strong>Pipeline templates.</strong> Set up common data flows (CDC from PostgreSQL to Kafka, search indexing from MongoDB to OpenSearch) with pre-built templates rather than wiring everything together manually.</li>
<li><strong>Predictive autoscaling.</strong> FoundryDB tracks CPU, memory, storage, and connection trends over time, then scales proactively before your application is affected.</li>
<li><strong>Database forking.</strong> Create an instant copy of any database from a backup or point-in-time snapshot. Use it for testing schema changes, running analytics, or debugging production issues without touching the live database.</li>
<li><strong>7 metrics export destinations.</strong> Send database metrics to Grafana Cloud, Datadog, New Relic, Prometheus remote write, InfluxDB, CloudWatch, or a custom webhook. DigitalOcean locks you into their built-in dashboard.</li>
<li><strong>Query-level analytics.</strong> See the slowest queries, most frequent queries, and lock contention patterns directly in the dashboard. No need to enable <code>pg_stat_statements</code> manually or parse slow query logs.</li>
<li><strong>EU infrastructure.</strong> All FoundryDB services run in European data centers by default. No special configuration or pricing tier required for GDPR compliance.</li>
</ul>
<p>Whether you are migrating one database or consolidating PostgreSQL, MySQL, and MongoDB onto a single platform, the process follows the same pattern: export, create, import, verify. Each engine's standard tooling works exactly as expected because FoundryDB runs the native database engines with no proxy layers or compatibility shims.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="migration" term="migration"/>
        <category label="digitalocean" term="digitalocean"/>
        <category label="postgresql" term="postgresql"/>
        <category label="mysql" term="mysql"/>
        <category label="mongodb" term="mongodb"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Migrate from Heroku Postgres to FoundryDB in 10 Minutes]]></title>
        <id>https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb</id>
        <link href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb"/>
        <updated>2026-04-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Step-by-step guide to migrating your Heroku Postgres database to FoundryDB with zero downtime.]]></summary>
        <content type="html"><![CDATA[<p>Heroku wound down its free tier in November 2022, and since then the managed Postgres add-on has remained a solid but limited option. If you have been hitting walls with single-engine lock-in, basic monitoring dashboards, no point-in-time recovery on lower plans, and the lack of multi-node high availability, it may be time to move. FoundryDB gives you a full-featured PostgreSQL service (plus six other engines) with automated HA, PITR, predictive autoscaling, and EU-hosted infrastructure, all manageable from a single CLI.</p>
<p>This guide walks you through a complete migration from Heroku Postgres to FoundryDB. The entire process takes about 10 minutes for a typical application database.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-migrate-from-heroku-postgres">Why Migrate from Heroku Postgres?<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#why-migrate-from-heroku-postgres" class="hash-link" aria-label="Direct link to Why Migrate from Heroku Postgres?" title="Direct link to Why Migrate from Heroku Postgres?">​</a></h2>
<p>Heroku Postgres serves many teams well for getting started, but production workloads often outgrow it:</p>
<ul>
<li><strong>Single engine only.</strong> Heroku offers PostgreSQL and nothing else. If your architecture needs Redis-compatible caching, Kafka for event streaming, or MongoDB for document storage, you need separate providers.</li>
<li><strong>No multi-node HA on standard plans.</strong> Automatic failover requires Premium or Enterprise tiers. On Standard plans, a hardware failure means downtime.</li>
<li><strong>Basic monitoring.</strong> Heroku provides pg<!-- -->:info<!-- --> and a simple dashboard. There is no query-level performance analysis, no predictive autoscaling, and no custom alerting rules.</li>
<li><strong>No point-in-time recovery on lower tiers.</strong> PITR is only available on Premium plans and above. Standard plans get periodic snapshots with potential data loss windows.</li>
<li><strong>US-centric infrastructure.</strong> Heroku runs on AWS, primarily in the US. EU data residency requires careful plan selection and comes at a premium.</li>
</ul>
<p>FoundryDB addresses all of these: seven database engines on one platform, multi-node HA from day one, PITR on every plan, predictive autoscaling, and EU-hosted infrastructure by default.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h2>
<p>Before starting, make sure you have:</p>
<ul>
<li><strong>Heroku CLI</strong> installed and authenticated (<code>heroku login</code>)</li>
<li><strong>A FoundryDB account</strong> at <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">foundrydb.com</a></li>
<li><strong>The fdb CLI</strong> installed (<code>brew install foundrydb/tap/fdb</code> or download from the dashboard)</li>
<li><strong>pg_restore</strong> available locally (comes with any PostgreSQL client installation)</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-export-your-database-from-heroku">Step 1: Export Your Database from Heroku<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#step-1-export-your-database-from-heroku" class="hash-link" aria-label="Direct link to Step 1: Export Your Database from Heroku" title="Direct link to Step 1: Export Your Database from Heroku">​</a></h2>
<p>First, capture a fresh backup of your Heroku Postgres database:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Capture a new backup</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">heroku pg:backups:capture </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--app</span><span class="token plain"> my-heroku-app</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Download the backup to your local machine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">heroku pg:backups:download </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--app</span><span class="token plain"> my-heroku-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This creates a file called <code>latest.dump</code> in your current directory. The file is in PostgreSQL's custom dump format, which supports parallel restore and selective table restoration.</p>
<p>For larger databases, you can check the backup size before downloading:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">heroku pg:backups </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--app</span><span class="token plain"> my-heroku-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="step-2-create-a-postgresql-service-on-foundrydb">Step 2: Create a PostgreSQL Service on FoundryDB<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#step-2-create-a-postgresql-service-on-foundrydb" class="hash-link" aria-label="Direct link to Step 2: Create a PostgreSQL Service on FoundryDB" title="Direct link to Step 2: Create a PostgreSQL Service on FoundryDB">​</a></h2>
<p>Create a new PostgreSQL instance using the FoundryDB CLI:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --database-type postgresql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">17</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --plan-name tier-2 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-size-gb </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> my-app-db </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> se-sto1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This provisions a PostgreSQL 17 instance with 2 vCPUs, 4 GB RAM, and 50 GB of NVMe storage. The service is ready in about 3 to 5 minutes. You can monitor the provisioning status:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb status my-app-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Wait until the status shows <code>Running</code> before proceeding.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-get-your-connection-details">Step 3: Get Your Connection Details<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#step-3-get-your-connection-details" class="hash-link" aria-label="Direct link to Step 3: Get Your Connection Details" title="Direct link to Step 3: Get Your Connection Details">​</a></h2>
<p>Retrieve the connection string for your new database:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-app-db </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--info</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This outputs the host, port, username, password, and a full connection URI. Note the host (it will look like <code>my-app-db-abc123.db.foundrydb.com</code>), username, and password for the next step.</p>
<p>You can also reveal credentials for a specific user:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb </span><span class="token function" style="color:rgb(220, 220, 170)">users</span><span class="token plain"> my-app-db --reveal-password</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="step-4-import-your-data">Step 4: Import Your Data<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#step-4-import-your-data" class="hash-link" aria-label="Direct link to Step 4: Import Your Data" title="Direct link to Step 4: Import Your Data">​</a></h2>
<p>Use <code>pg_restore</code> to load the Heroku dump into your FoundryDB instance:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">pg_restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--host</span><span class="token plain"> my-app-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--port</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">5432</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--username</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--dbname</span><span class="token plain"> defaultdb </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-owner </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-privileges </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--verbose</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  latest.dump</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Enter the password when prompted. The <code>--no-owner</code> and <code>--no-privileges</code> flags skip Heroku-specific role assignments that do not exist on your new instance.</p>
<p>For larger databases, use parallel restore to speed things up:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">pg_restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--host</span><span class="token plain"> my-app-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--port</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">5432</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--username</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--dbname</span><span class="token plain"> defaultdb </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-owner </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-privileges </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--jobs</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  latest.dump</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="step-5-update-your-applications-database_url">Step 5: Update Your Application's DATABASE_URL<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#step-5-update-your-applications-database_url" class="hash-link" aria-label="Direct link to Step 5: Update Your Application's DATABASE_URL" title="Direct link to Step 5: Update Your Application's DATABASE_URL">​</a></h2>
<p>Replace your Heroku database connection string with the FoundryDB one. The new URL follows standard PostgreSQL format:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">postgresql://app_user:YOUR_PASSWORD@my-app-db-abc123.db.foundrydb.com:5432/defaultdb?sslmode=require</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>If your app reads <code>DATABASE_URL</code> from environment variables, update it in your deployment configuration. For example, in a Docker Compose setup:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">DATABASE_URL</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> postgresql</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain">//app_user</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain">YOUR_PASSWORD@my</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">app</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">abc123.db.foundrydb.com</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain">5432/defaultdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">?</span><span class="token plain">sslmode=require</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>FoundryDB uses auto-renewed TLS certificates, so <code>sslmode=require</code> (or <code>verify-full</code>) works out of the box with no certificate management on your part.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-6-verify-the-migration">Step 6: Verify the Migration<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#step-6-verify-the-migration" class="hash-link" aria-label="Direct link to Step 6: Verify the Migration" title="Direct link to Step 6: Verify the Migration">​</a></h2>
<p>Connect to your new database and run verification queries:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Connect interactively</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-app-db</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Or use psql directly</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">PGPASSWORD</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">YOUR_PASSWORD psql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"host=my-app-db-abc123.db.foundrydb.com user=app_user dbname=defaultdb sslmode=require"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Run these checks to confirm everything migrated correctly:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Check table count</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">count</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token operator" style="color:rgb(212, 212, 212)">*</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> information_schema</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token keyword" style="color:rgb(86, 156, 214)">tables</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> table_schema </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'public'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Check row counts for key tables</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> schemaname</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> relname</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> n_live_tup</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> pg_stat_user_tables</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> n_live_tup </span><span class="token keyword" style="color:rgb(86, 156, 214)">DESC</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">LIMIT</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">20</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Verify indexes exist</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> indexname</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> tablename </span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> pg_indexes </span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> schemaname </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'public'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Test a representative query from your application</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> users </span><span class="token keyword" style="color:rgb(86, 156, 214)">LIMIT</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">5</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Compare the table count and row counts against your Heroku instance to confirm data integrity.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-you-gain-after-migrating">What You Gain After Migrating<a href="https://docs.foundrydb.com/blog/migrate-from-heroku-postgres-to-foundrydb#what-you-gain-after-migrating" class="hash-link" aria-label="Direct link to What You Gain After Migrating" title="Direct link to What You Gain After Migrating">​</a></h2>
<p>Moving from Heroku Postgres to FoundryDB gives you immediate access to:</p>
<ul>
<li><strong>7 database engines.</strong> PostgreSQL, MySQL, MongoDB, Valkey, Kafka, OpenSearch, and Babelfish (SQL Server wire protocol). Manage everything from one dashboard and one CLI.</li>
<li><strong>Multi-node HA.</strong> Add read replicas and automatic failover with a single command. No plan upgrade required.</li>
<li><strong>Point-in-time recovery.</strong> Every plan includes continuous WAL archiving and PITR. Restore to any second within your retention window.</li>
<li><strong>Predictive autoscaling.</strong> FoundryDB monitors resource trends and scales compute and storage before you hit limits, not after.</li>
<li><strong>EU hosting by default.</strong> All infrastructure runs in European data centers (Stockholm), simplifying GDPR compliance.</li>
<li><strong>TLS auto-renewal.</strong> Certificates are provisioned and renewed automatically. No manual certificate management.</li>
<li><strong>Extensions ecosystem.</strong> Enable pgvector, PostGIS, TimescaleDB, and dozens of other extensions directly from the dashboard or CLI.</li>
<li><strong>Real-time query analytics.</strong> Monitor slow queries, connection counts, replication lag, and custom metrics with built-in dashboards and alerting.</li>
</ul>
<p>The migration is a one-time effort. Once your data is on FoundryDB, you have a modern database platform that scales with your application.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="migration" term="migration"/>
        <category label="heroku" term="heroku"/>
        <category label="postgresql" term="postgresql"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Migrate from PlanetScale to FoundryDB MySQL]]></title>
        <id>https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql</id>
        <link href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql"/>
        <updated>2026-04-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Move your MySQL database from PlanetScale to FoundryDB with full GTID replication support.]]></summary>
        <content type="html"><![CDATA[<p>PlanetScale removed its free tier in April 2024 and raised prices across the board, pushing many teams to re-evaluate their MySQL hosting. Beyond pricing, PlanetScale runs on Vitess, a sharding proxy that sits between your application and MySQL. While Vitess handles horizontal scaling well, it introduces compatibility quirks that can surprise you: no foreign key enforcement, limited support for certain joins, and behavior differences from native MySQL. If you want a standard MySQL experience with native replication, foreign keys, and no proxy layer, FoundryDB is a direct path forward.</p>
<p>This guide walks through exporting your database from PlanetScale and importing it into FoundryDB's native MySQL service. The process works for databases of any size, from small hobby projects to production workloads.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-migrate-from-planetscale">Why Migrate from PlanetScale?<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#why-migrate-from-planetscale" class="hash-link" aria-label="Direct link to Why Migrate from PlanetScale?" title="Direct link to Why Migrate from PlanetScale?">​</a></h2>
<p>PlanetScale built an impressive product on Vitess, but the tradeoffs are real:</p>
<ul>
<li><strong>No foreign key enforcement.</strong> PlanetScale does not enforce foreign key constraints. Your application must handle referential integrity in code. This means bugs in your application logic can silently corrupt data relationships.</li>
<li><strong>Vitess compatibility gaps.</strong> Certain SQL features behave differently or are unavailable: some subquery patterns, specific JOIN operations, and DDL statements have restrictions. You are running "MySQL-like" rather than MySQL itself.</li>
<li><strong>Pricing increases.</strong> After removing the free tier, PlanetScale's Scaler plan starts at $39/month for 5 GB of storage. FoundryDB's tier-2 plan with 50 GB of NVMe storage offers more resources at a competitive price.</li>
<li><strong>Single engine.</strong> PlanetScale is MySQL-only. If your stack needs Redis-compatible caching, PostgreSQL for analytics, or Kafka for event streaming, you need additional providers.</li>
<li><strong>No GTID replication.</strong> PlanetScale uses Vitess-level replication rather than native MySQL GTID replication. This limits your ability to set up standard MySQL replicas or integrate with tools that expect GTID-based binlog positions.</li>
</ul>
<p>FoundryDB runs native MySQL 8.4 with full foreign key support, GTID-based replication, ProxySQL connection pooling, and six additional database engines on the same platform.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h2>
<p>Before starting, make sure you have:</p>
<ul>
<li><strong>PlanetScale CLI</strong> (<code>pscale</code>) installed and authenticated</li>
<li><strong>A FoundryDB account</strong> at <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">foundrydb.com</a></li>
<li><strong>The fdb CLI</strong> installed (<code>brew install foundrydb/tap/fdb</code> or download from the dashboard)</li>
<li><strong>MySQL client tools</strong> available locally (<code>mysqldump</code> and <code>mysql</code> commands)</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-export-your-database-from-planetscale">Step 1: Export Your Database from PlanetScale<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#step-1-export-your-database-from-planetscale" class="hash-link" aria-label="Direct link to Step 1: Export Your Database from PlanetScale" title="Direct link to Step 1: Export Your Database from PlanetScale">​</a></h2>
<p>PlanetScale provides a built-in dump command through its CLI:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">pscale database dump my-planetscale-db main </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--output</span><span class="token plain"> ./dump</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This exports all tables from the <code>main</code> branch into individual SQL files in the <code>./dump</code> directory. Each table gets its own file containing the schema and data.</p>
<p>Alternatively, if you prefer a single dump file, you can connect directly and use <code>mysqldump</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Get your PlanetScale connection string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">pscale connect my-planetscale-db main </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--port</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">3309</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># In another terminal, dump using mysqldump</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysqldump </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--host</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">127.0</span><span class="token plain">.0.1 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--port</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">3309</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--user</span><span class="token plain"> YOUR_PSCALE_USER </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --set-gtid-purged</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">OFF </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --no-tablespaces </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --single-transaction </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  my_database </span><span class="token operator" style="color:rgb(212, 212, 212)">&gt;</span><span class="token plain"> planetscale-dump.sql</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>--set-gtid-purged=OFF</code> flag is important because PlanetScale (Vitess) does not use standard MySQL GTID, so the dump should not include GTID metadata.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-create-a-mysql-service-on-foundrydb">Step 2: Create a MySQL Service on FoundryDB<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#step-2-create-a-mysql-service-on-foundrydb" class="hash-link" aria-label="Direct link to Step 2: Create a MySQL Service on FoundryDB" title="Direct link to Step 2: Create a MySQL Service on FoundryDB">​</a></h2>
<p>Provision a new MySQL instance:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --database-type mysql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">8.4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --plan-name tier-2 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-size-gb </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> my-mysql-db </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> se-sto1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This creates a MySQL 8.4 instance with 2 vCPUs, 4 GB RAM, and 50 GB NVMe storage. Monitor provisioning:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb status my-mysql-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Wait until the status shows <code>Running</code>. Provisioning typically takes 3 to 5 minutes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-get-your-connection-details">Step 3: Get Your Connection Details<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#step-3-get-your-connection-details" class="hash-link" aria-label="Direct link to Step 3: Get Your Connection Details" title="Direct link to Step 3: Get Your Connection Details">​</a></h2>
<p>Retrieve your FoundryDB MySQL connection information:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-mysql-db </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--info</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This shows the host, port, username, password, and connection URI. Note these values for the import step.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-import-your-data">Step 4: Import Your Data<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#step-4-import-your-data" class="hash-link" aria-label="Direct link to Step 4: Import Your Data" title="Direct link to Step 4: Import Your Data">​</a></h2>
<p>If you used the PlanetScale CLI dump (multiple files in a directory), import each file:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">for</span><span class="token plain"> </span><span class="token for-or-select variable" style="color:rgb(156, 220, 254)">f</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">in</span><span class="token plain"> ./dump/*.sql</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">do</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  mysql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-h</span><span class="token plain"> my-mysql-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-pYOUR_PASSWORD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    --ssl-mode</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">REQUIRED </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    defaultdb </span><span class="token operator" style="color:rgb(212, 212, 212)">&lt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"</span><span class="token string variable" style="color:rgb(156, 220, 254)">$f</span><span class="token string" style="color:rgb(206, 145, 120)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">done</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>If you used a single <code>mysqldump</code> file:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-h</span><span class="token plain"> my-mysql-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-pYOUR_PASSWORD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --ssl-mode</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">REQUIRED </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  defaultdb </span><span class="token operator" style="color:rgb(212, 212, 212)">&lt;</span><span class="token plain"> planetscale-dump.sql</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>For large databases, you may want to disable key checks during import for better performance:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-h</span><span class="token plain"> my-mysql-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-pYOUR_PASSWORD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --ssl-mode</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">REQUIRED </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-e</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"SET GLOBAL foreign_key_checks=0; SOURCE planetscale-dump.sql; SET GLOBAL foreign_key_checks=1;"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  defaultdb</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="step-5-update-your-application-connection-strings">Step 5: Update Your Application Connection Strings<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#step-5-update-your-application-connection-strings" class="hash-link" aria-label="Direct link to Step 5: Update Your Application Connection Strings" title="Direct link to Step 5: Update Your Application Connection Strings">​</a></h2>
<p>Replace your PlanetScale connection string with the FoundryDB one:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysql://app_user:YOUR_PASSWORD@my-mysql-db-abc123.db.foundrydb.com:3306/defaultdb?ssl-mode=REQUIRED</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Most MySQL client libraries accept this URI format. For frameworks that use individual parameters:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Example: Rails database.yml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token key atrule">production</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">adapter</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> mysql2</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">host</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">mysql</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">abc123.db.foundrydb.com</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">port</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">3306</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">username</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> app_user</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">password</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> YOUR_PASSWORD</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">database</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> defaultdb</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">ssl_mode</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> required</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="step-6-verify-the-migration">Step 6: Verify the Migration<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#step-6-verify-the-migration" class="hash-link" aria-label="Direct link to Step 6: Verify the Migration" title="Direct link to Step 6: Verify the Migration">​</a></h2>
<p>Connect and run verification queries:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb connect my-mysql-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Or directly with the MySQL client:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mysql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-h</span><span class="token plain"> my-mysql-db-abc123.db.foundrydb.com </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> app_user </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-pYOUR_PASSWORD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --ssl-mode</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">REQUIRED </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  defaultdb</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Run these checks:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Check all tables imported</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">TABLES</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Verify row counts on key tables</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> table_name</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> table_rows</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> information_schema</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token keyword" style="color:rgb(86, 156, 214)">tables</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> table_schema </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'defaultdb'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> table_rows </span><span class="token keyword" style="color:rgb(86, 156, 214)">DESC</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Verify foreign keys are enforced (this was impossible on PlanetScale)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">TABLE</span><span class="token plain"> orders</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Test a foreign key constraint</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">INSERT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">INTO</span><span class="token plain"> orders </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">user_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> total</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">VALUES</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token number" style="color:rgb(181, 206, 168)">999999</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">10.00</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Should fail if user_id 999999 doesn't exist in users table</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Check indexes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">INDEX</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> your_main_table</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 foreign key test is the most important verification. On PlanetScale, the INSERT with a non-existent <code>user_id</code> would succeed silently. On FoundryDB's native MySQL, it correctly rejects the statement with a foreign key violation error.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-you-gain-after-migrating">What You Gain After Migrating<a href="https://docs.foundrydb.com/blog/migrate-from-planetscale-to-foundrydb-mysql#what-you-gain-after-migrating" class="hash-link" aria-label="Direct link to What You Gain After Migrating" title="Direct link to What You Gain After Migrating">​</a></h2>
<p>Switching from PlanetScale to FoundryDB gives you:</p>
<ul>
<li><strong>Native MySQL, not a proxy.</strong> Your queries hit MySQL directly. No Vitess translation layer, no compatibility surprises. Standard MySQL documentation applies exactly as written.</li>
<li><strong>Foreign key enforcement.</strong> Referential integrity is handled by the database engine where it belongs. Remove the workarounds from your application code.</li>
<li><strong>GTID-based replication.</strong> FoundryDB uses standard MySQL GTID replication for read replicas and HA. This is compatible with the entire MySQL ecosystem of tools and monitoring.</li>
<li><strong>ProxySQL connection pooling.</strong> Enable the ProxySQL addon for intelligent query routing, connection multiplexing, and read/write splitting across replicas.</li>
<li><strong>7 engines on one platform.</strong> Need Valkey for caching, Kafka for events, or PostgreSQL for a different service? Create them from the same dashboard and CLI. One bill, one set of credentials.</li>
<li><strong>Predictive autoscaling.</strong> FoundryDB monitors CPU, memory, storage, and connection trends, then scales resources proactively before your application feels the pressure.</li>
<li><strong>Point-in-time recovery.</strong> Continuous binary log archiving lets you restore to any second within your retention window. No more scheduled-snapshot-only recovery.</li>
<li><strong>EU infrastructure.</strong> All data stays in European data centers by default, simplifying compliance requirements.</li>
</ul>
<p>The migration from PlanetScale is straightforward because you are moving from a MySQL-compatible system to actual MySQL. Your existing queries, ORMs, and tools will work without modification, and features that were restricted under Vitess (foreign keys, certain joins, subqueries) start working immediately.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="migration" term="migration"/>
        <category label="planetscale" term="planetscale"/>
        <category label="mysql" term="mysql"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI Agents Need Databases Too: How FoundryDB Serves the Agent Era]]></title>
        <id>https://docs.foundrydb.com/blog/ai-agents-need-databases-too</id>
        <link href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AI agents are creating databases programmatically. FoundryDB provides the infrastructure they need: fast provisioning, MCP server, SDKs, and presets.]]></summary>
        <content type="html"><![CDATA[<p>Something fundamental shifted in how databases get created. In 2024, most database provisioning was triggered by a human clicking a button in a dashboard or running a CLI command. By early 2026, Neon reported that 80% of new databases on their platform were created by AI agents, not humans. The database is becoming infrastructure that agents provision, configure, and tear down as part of their workflows.</p>
<p>This changes what a managed database platform needs to provide. Agents do not use dashboards. They do not read documentation the way engineers do. They need fast, programmatic interfaces with predictable behavior. They need databases that spin up in seconds, clean themselves up when no longer needed, and integrate natively with agent frameworks.</p>
<p>We built FoundryDB's agent infrastructure to meet these requirements.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-agents-need-from-a-database-platform">What Agents Need from a Database Platform<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#what-agents-need-from-a-database-platform" class="hash-link" aria-label="Direct link to What Agents Need from a Database Platform" title="Direct link to What Agents Need from a Database Platform">​</a></h2>
<p>AI agents have different requirements than human operators. Understanding these differences shaped our design decisions.</p>
<p><strong>Fast provisioning.</strong> An agent building a RAG pipeline needs a PostgreSQL instance with pgvector now, not in 10 minutes. When database creation is part of an agent's planning and execution loop, provisioning latency directly impacts the agent's task completion time. FoundryDB provisions from pre-built templates, with most services ready to accept connections within 2-3 minutes.</p>
<p><strong>Ephemeral databases.</strong> Many agent workflows create databases for a specific task: index a document corpus, run an analysis, generate a report. When the task is done, the database should be cleaned up automatically. FoundryDB supports TTL (time-to-live) on services, so agents can create a database that auto-deletes after a specified duration.</p>
<p><strong>Programmatic management.</strong> Agents interact through APIs and tool calls, not dashboards. Every FoundryDB operation is available through our REST API, CLI, TypeScript SDK, Python SDK, and MCP (Model Context Protocol) server. Agents can create, configure, query, scale, and delete databases without human intervention.</p>
<p><strong>Presets for common patterns.</strong> Agents should not need to figure out which PostgreSQL extensions to enable for vector search or what Kafka topic configuration works best for event sourcing. FoundryDB provides 16 presets that pre-configure services for specific use cases. An agent says "I need a database for vector search" and gets a PostgreSQL instance with pgvector enabled, HNSW indexes configured, and appropriate resource allocation.</p>
<p><strong>Metadata and labeling.</strong> When agents create dozens of databases, operators need to understand what each one is for. FoundryDB supports service labels and metadata that agents can set at creation time: <code>agent_framework: langchain</code>, <code>agent_purpose: rag-pipeline</code>, <code>agent_run_id: abc-123</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-mcp-server">The MCP Server<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#the-mcp-server" class="hash-link" aria-label="Direct link to The MCP Server" title="Direct link to The MCP Server">​</a></h2>
<p>The Model Context Protocol (MCP) is becoming the standard way for LLMs and agents to interact with external tools. FoundryDB ships an MCP server that exposes database management as tool calls that any MCP-compatible agent can use.</p>
<p>Here is what it looks like when an agent uses the MCP server to create a database:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">Agent: "Create a PostgreSQL database with pgvector for storing</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        document embeddings. Use the Helsinki zone and tier-3 plan."</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">MCP Tool Call: foundrydb.create_service({</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  name: "doc-embeddings-a3f2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  engine: "postgresql",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  version: "17",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  plan: "tier-3",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  zone: "eu-helsinki",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  storage_gb: 50,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  preset: "pgvector",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  labels: {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    agent_framework: "claude",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    agent_purpose: "document-embeddings",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    created_by: "agent"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  },</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  ttl: "24h"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">})</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">Response: {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  id: "svc_x7k2m9p4",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  status: "provisioning",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  connection_uri: "postgresql://app_user:***@doc-embeddings-a3f2.foundrydb.com/defaultdb?sslmode=verify-full",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  estimated_ready: "2m"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 MCP server handles authentication, input validation, and returns structured responses that the agent can parse and act on. The agent does not need to know about REST endpoints or HTTP headers.</p>
<p>To configure the MCP server with Claude Desktop or any MCP-compatible client:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"mcpServers"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token property">"foundrydb"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"npx"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"args"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"@foundrydb/mcp-server"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"env"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token property">"FOUNDRYDB_API_KEY"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"your-api-key"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="sdk-integration">SDK Integration<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#sdk-integration" class="hash-link" aria-label="Direct link to SDK Integration" title="Direct link to SDK Integration">​</a></h2>
<p>For agents built with Python or TypeScript, the FoundryDB SDKs provide typed, idiomatic interfaces for database management.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="python-sdk">Python SDK<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#python-sdk" class="hash-link" aria-label="Direct link to Python SDK" title="Direct link to Python SDK">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> foundrydb </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> FoundryDB</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> FoundryDB</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">api_key</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"your-api-key"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Create a service with a preset</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">service </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> fdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">services</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">create</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    name</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"agent-rag-store"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    engine</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    version</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"17"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    plan</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"tier-3"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    zone</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"eu-helsinki"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    storage_gb</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    preset</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"pgvector"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    labels</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string" style="color:rgb(206, 145, 120)">"agent_framework"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"langchain"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"agent_purpose"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"rag"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    ttl</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"12h"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain">  </span><span class="token comment" style="color:rgb(106, 153, 85)"># Auto-delete after 12 hours</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Wait for the service to be ready</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">service</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">wait_until_ready</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">timeout</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style="color:rgb(181, 206, 168)">300</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Get connection details</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">conn_info </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> service</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">connection_info</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">print</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">f"Connect: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string-interpolation interpolation">conn_info</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token string-interpolation interpolation">uri</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># When the agent is done, delete immediately (or let TTL handle it)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">service</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">delete</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="typescript-sdk">TypeScript SDK<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#typescript-sdk" class="hash-link" aria-label="Direct link to TypeScript SDK" title="Direct link to TypeScript SDK">​</a></h3>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword module" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">FoundryDB</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'@foundrydb/sdk'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">const</span><span class="token plain"> fdb </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">new</span><span class="token plain"> </span><span class="token class-name maybe-class-name" style="color:rgb(78, 201, 176)">FoundryDB</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> apiKey</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'your-api-key'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">const</span><span class="token plain"> service </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(86, 156, 214)">await</span><span class="token plain"> fdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token property-access">services</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">create</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'agent-session-cache'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  engine</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'valkey'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  version</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'8.1'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  plan</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'tier-2'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  zone</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'eu-helsinki'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  storageGb</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">20</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  labels</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> agent_framework</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'crewai'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> agent_purpose</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'session-cache'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  ttl</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'6h'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(86, 156, 214)">await</span><span class="token plain"> service</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">waitUntilReady</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> host</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> port</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> service</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">connectionInfo</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">// Use the Valkey instance...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="cli-for-scripting">CLI for Scripting<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#cli-for-scripting" class="hash-link" aria-label="Direct link to CLI for Scripting" title="Direct link to CLI for Scripting">​</a></h3>
<p>For agents that shell out to CLI tools:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Create and wait in one command</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> agent-workspace-</span><span class="token variable" style="color:rgb(156, 220, 254)">$(</span><span class="token variable" style="color:rgb(156, 220, 254)">uuidgen </span><span class="token variable operator" style="color:rgb(212, 212, 212)">|</span><span class="token variable" style="color:rgb(156, 220, 254)"> </span><span class="token variable function" style="color:rgb(220, 220, 170)">head</span><span class="token variable" style="color:rgb(156, 220, 254)"> </span><span class="token variable parameter variable" style="color:rgb(156, 220, 254)">-c</span><span class="token variable" style="color:rgb(156, 220, 254)"> </span><span class="token variable number" style="color:rgb(181, 206, 168)">8</span><span class="token variable" style="color:rgb(156, 220, 254)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> postgresql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">17</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-2 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--preset</span><span class="token plain"> pgvector </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--label</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">agent_framework</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">autogen </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--label</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">agent_purpose</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">analysis </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--ttl</span><span class="token plain"> 4h </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--wait</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--output</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># List all agent-created services</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services list </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--label</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">created_by</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">agent </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--output</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Clean up all expired agent services (TTL handles this, but manual cleanup is available)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services list </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--label</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">created_by</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">agent </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--status</span><span class="token plain"> stopped </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--output</span><span class="token plain"> json </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> jq </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-r</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'.[].id'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">xargs</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-I</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> fdb services delete </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="common-agent-architectures">Common Agent Architectures<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#common-agent-architectures" class="hash-link" aria-label="Direct link to Common Agent Architectures" title="Direct link to Common Agent Architectures">​</a></h2>
<p>Here are the most common multi-engine patterns we see agents deploying on FoundryDB.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="rag-pipeline-postgresql--valkey">RAG Pipeline (PostgreSQL + Valkey)<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#rag-pipeline-postgresql--valkey" class="hash-link" aria-label="Direct link to RAG Pipeline (PostgreSQL + Valkey)" title="Direct link to RAG Pipeline (PostgreSQL + Valkey)">​</a></h3>
<p>The most popular pattern. PostgreSQL with pgvector stores document embeddings. Valkey caches query results and stores conversation history. Kafka is optional for high-throughput document ingestion.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Agent creates a complete RAG stack</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">vector_db </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> fdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">services</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">create</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    name</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"rag-vectors"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    engine</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    preset</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"pgvector"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    plan</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"tier-4"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    storage_gb</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style="color:rgb(181, 206, 168)">100</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    zone</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"eu-helsinki"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    labels</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string" style="color:rgb(206, 145, 120)">"stack"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"rag"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"role"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"vector-store"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">cache </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> fdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">services</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">create</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    name</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"rag-cache"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    engine</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"valkey"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    plan</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"tier-2"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    storage_gb</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style="color:rgb(181, 206, 168)">20</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    zone</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"eu-helsinki"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    labels</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string" style="color:rgb(206, 145, 120)">"stack"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"rag"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"role"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"cache"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="conversational-ai-mongodb--valkey">Conversational AI (MongoDB + Valkey)<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#conversational-ai-mongodb--valkey" class="hash-link" aria-label="Direct link to Conversational AI (MongoDB + Valkey)" title="Direct link to Conversational AI (MongoDB + Valkey)">​</a></h3>
<p>MongoDB stores conversation histories, user profiles, and tool call logs. Its flexible schema adapts to the evolving structure of agent interactions without migrations. Valkey handles session state and rate limiting.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="multi-agent-coordination-kafka--mongodb--postgresql">Multi-Agent Coordination (Kafka + MongoDB + PostgreSQL)<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#multi-agent-coordination-kafka--mongodb--postgresql" class="hash-link" aria-label="Direct link to Multi-Agent Coordination (Kafka + MongoDB + PostgreSQL)" title="Direct link to Multi-Agent Coordination (Kafka + MongoDB + PostgreSQL)">​</a></h3>
<p>When multiple agents collaborate (CrewAI, AutoGen, LangGraph), Kafka serves as the event bus for inter-agent communication. MongoDB stores agent state and task results. PostgreSQL handles structured data that agents query with SQL.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="ephemeral-analysis-postgresql-with-ttl">Ephemeral Analysis (PostgreSQL with TTL)<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#ephemeral-analysis-postgresql-with-ttl" class="hash-link" aria-label="Direct link to Ephemeral Analysis (PostgreSQL with TTL)" title="Direct link to Ephemeral Analysis (PostgreSQL with TTL)">​</a></h3>
<p>Data analysts use agents to create temporary databases, load datasets, run complex queries, and export results. The database auto-deletes after the analysis is complete.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Temporary analysis database that self-destructs in 2 hours</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">analysis_db </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> fdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">services</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">create</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    name</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">f"analysis-</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string-interpolation interpolation">task_id</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    engine</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    plan</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"tier-3"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    storage_gb</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    zone</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"eu-helsinki"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    ttl</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"2h"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    labels</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string" style="color:rgb(206, 145, 120)">"agent_purpose"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"data-analysis"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"task_id"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> task_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="service-labels-and-observability">Service Labels and Observability<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#service-labels-and-observability" class="hash-link" aria-label="Direct link to Service Labels and Observability" title="Direct link to Service Labels and Observability">​</a></h2>
<p>When agents create databases autonomously, observability becomes critical. Who created this database? Why? Is it still needed? FoundryDB's label system provides the answers.</p>
<p>Every service supports arbitrary key-value labels. We recommend a standard set for agent-created services:</p>
<table><thead><tr><th>Label</th><th>Purpose</th><th>Example</th></tr></thead><tbody><tr><td><code>created_by</code></td><td>Who created it</td><td><code>agent</code>, <code>human</code>, <code>ci-pipeline</code></td></tr><tr><td><code>agent_framework</code></td><td>Which framework</td><td><code>langchain</code>, <code>crewai</code>, <code>autogen</code>, <code>claude</code></td></tr><tr><td><code>agent_purpose</code></td><td>What it is for</td><td><code>rag</code>, <code>session-cache</code>, <code>analysis</code></td></tr><tr><td><code>agent_run_id</code></td><td>Specific run identifier</td><td><code>run_a3f2b7c1</code></td></tr><tr><td><code>stack</code></td><td>Multi-service grouping</td><td><code>rag-pipeline</code>, <code>ecommerce</code></td></tr><tr><td><code>environment</code></td><td>Deployment environment</td><td><code>development</code>, <code>staging</code>, <code>production</code></td></tr></tbody></table>
<p>These labels are queryable through the API and visible in the dashboard. Operators can filter by <code>created_by=agent</code> to see all agent-provisioned databases, or by <code>agent_framework=langchain</code> to see databases created by a specific framework.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Dashboard view: all agent-created services</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services list </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--label</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">created_by</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">agent</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Cost tracking: total spend by agent framework</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb billing usage --group-by label:agent_framework</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Cleanup: find agent databases older than 7 days</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services list </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--label</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">created_by</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">agent --created-before 7d</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="building-for-the-agent-era">Building for the Agent Era<a href="https://docs.foundrydb.com/blog/ai-agents-need-databases-too#building-for-the-agent-era" class="hash-link" aria-label="Direct link to Building for the Agent Era" title="Direct link to Building for the Agent Era">​</a></h2>
<p>The shift toward agent-driven database provisioning is accelerating. As agent frameworks mature and more workflows become autonomous, the database platform needs to be a first-class participant in the agent ecosystem, not an afterthought that requires human intervention.</p>
<p>FoundryDB's approach is to meet agents where they are: MCP for LLM-native tool use, SDKs for framework integration, presets for instant configuration, TTL for lifecycle management, and labels for observability. The database becomes another tool in the agent's toolkit, provisioned and managed as naturally as making an API call or reading a file.</p>
<p>Explore the <a href="https://docs.foundrydb.com/getting-started/quick-start">AI agent infrastructure documentation</a> to integrate FoundryDB with your agent workflows. The MCP server is available today, and the Python and TypeScript SDKs support all service management operations.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="agents" term="agents"/>
        <category label="mcp" term="mcp"/>
        <category label="langchain" term="langchain"/>
        <category label="crewai" term="crewai"/>
        <category label="sdk" term="sdk"/>
        <category label="automation" term="automation"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Query Your Database in Plain English: FoundryDB's AI Query Console]]></title>
        <id>https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql</id>
        <link href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Translate natural language questions into SQL queries with FoundryDB's AI-powered query console. Safe, read-only, and context-aware across PostgreSQL, MySQL, and MongoDB.]]></summary>
        <content type="html"><![CDATA[<p>Most database dashboards give you a SQL editor and wish you luck. That works fine when you remember the exact name of the <code>pg_stat_user_tables</code> view or the difference between <code>information_schema.TABLES</code> in MySQL versus PostgreSQL. For everyone else, there is the AI Query Console.</p>
<p>FoundryDB's AI Query Console lets you type a question in plain English, translates it to a database-native SQL query using Claude, and executes it against your running service. The entire flow is read-only by design. You cannot accidentally drop a table by asking a question.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-works">How It Works<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#how-it-works" class="hash-link" aria-label="Direct link to How It Works" title="Direct link to How It Works">​</a></h2>
<p>The AI Query Console is a two-step pipeline: <strong>translate</strong>, then <strong>execute</strong>. These are separate API calls, which means you always see the generated SQL before anything runs against your database. You can review it, edit it, or discard it entirely.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-translate">Step 1: Translate<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#step-1-translate" class="hash-link" aria-label="Direct link to Step 1: Translate" title="Direct link to Step 1: Translate">​</a></h3>
<p>You send a natural language question to the translate endpoint. FoundryDB passes your question to Claude along with the database dialect (PostgreSQL or MySQL) and the engine version. Claude generates a read-only SQL query and a brief explanation of what it does.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">service-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/ai-query/translate </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"question": "Show the top 10 largest tables by size"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response includes the generated SQL, an explanation, and the database dialect used:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"sql"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"SELECT tablename, pg_total_relation_size(quote_ident(tablename)) AS size FROM pg_tables WHERE schemaname = 'public' ORDER BY size DESC LIMIT 10"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"explanation"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Lists the 10 largest tables in the public schema"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"database_type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>If Claude generates a query that violates safety rules, the <code>sql</code> field is returned empty and a <code>warning</code> field explains why the query was blocked.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-execute">Step 2: Execute<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#step-2-execute" class="hash-link" aria-label="Direct link to Step 2: Execute" title="Direct link to Step 2: Execute">​</a></h3>
<p>Once you have the SQL (or have edited it to your liking), you send it to the execute endpoint:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">service-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/ai-query/execute </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"sql": "SELECT tablename, pg_total_relation_size(quote_ident(tablename)) AS size FROM pg_tables WHERE schemaname = '</span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain">'</span><span class="token string" style="color:rgb(206, 145, 120)">'public'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain">'</span><span class="token string" style="color:rgb(206, 145, 120)">' ORDER BY size DESC LIMIT 10"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response contains column names, row data, the row count, and execution time in milliseconds:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"columns"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"tablename"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"size"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"rows"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"orders"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">2147483648</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"events"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1073741824</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"users"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">536870912</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"row_count"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">3</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"execution_ms"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">15</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"truncated"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Results are capped at 1,000 rows. If the result set exceeds that limit, <code>truncated</code> is set to <code>true</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="safety-guardrails">Safety Guardrails<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#safety-guardrails" class="hash-link" aria-label="Direct link to Safety Guardrails" title="Direct link to Safety Guardrails">​</a></h2>
<p>The AI Query Console enforces read-only access at three layers, so no single point of failure can allow a write operation.</p>
<p><strong>1. Prompt-level constraints.</strong> The system prompt instructs Claude to generate only <code>SELECT</code>, <code>SHOW</code>, <code>DESCRIBE</code>, and <code>EXPLAIN</code> statements. It explicitly forbids <code>INSERT</code>, <code>UPDATE</code>, <code>DELETE</code>, <code>DROP</code>, <code>CREATE</code>, <code>ALTER</code>, <code>TRUNCATE</code>, and multi-statement queries.</p>
<p><strong>2. Server-side SQL validation.</strong> Before execution, the controller parses the SQL and rejects anything that is not a recognized read-only statement. It strips comments, blocks semicolons (preventing multi-statement injection), and scans for dangerous keywords even inside subqueries and CTEs.</p>
<p><strong>3. Database-level read-only mode.</strong> The connection to your database is opened in read-only transaction mode. On PostgreSQL, this sets <code>default_transaction_read_only = ON</code> and a 30-second <code>statement_timeout</code>. On MySQL, it uses <code>SET SESSION TRANSACTION READ ONLY</code> and <code>max_execution_time = 30000</code>. Even if a write query somehow passes the first two layers, the database itself rejects it.</p>
<p>These layers are independent. A failure at the AI level is caught by validation. A failure at validation is caught by the database. Your data stays safe.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="supported-database-engines">Supported Database Engines<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#supported-database-engines" class="hash-link" aria-label="Direct link to Supported Database Engines" title="Direct link to Supported Database Engines">​</a></h2>
<table><thead><tr><th>Engine</th><th>Translate</th><th>Execute</th><th>Dialect-Aware System Catalogs</th></tr></thead><tbody><tr><td>PostgreSQL</td><td>Yes</td><td>Yes</td><td><code>pg_stat_statements</code>, <code>pg_stat_user_tables</code>, <code>pg_stat_activity</code>, <code>information_schema</code>, <code>pg_indexes</code>, <code>pg_class</code>, <code>pg_namespace</code></td></tr><tr><td>MySQL</td><td>Yes</td><td>Yes</td><td><code>information_schema</code>, <code>performance_schema</code>, <code>mysql</code> system database</td></tr></tbody></table>
<p>The translate endpoint generates dialect-correct SQL based on your service's engine type and version. If you have a PostgreSQL 17 service, it generates PostgreSQL 17-compatible queries. If you have a MySQL 8.4 service, it generates MySQL 8.4-compatible queries. You do not need to specify the dialect yourself.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="schema-context-awareness">Schema Context Awareness<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#schema-context-awareness" class="hash-link" aria-label="Direct link to Schema Context Awareness" title="Direct link to Schema Context Awareness">​</a></h2>
<p>When Claude generates SQL for your service, it knows the database dialect and version. This means it can reference engine-specific system views accurately. Ask a PostgreSQL service about slow queries, and it queries <code>pg_stat_statements</code>. Ask a MySQL service the same question, and it queries <code>performance_schema</code>.</p>
<p>The translate endpoint also accepts an optional <code>database_name</code> parameter. By default, queries run against <code>defaultdb</code> (the default database created for every FoundryDB service). If you want to query a different database on the same service, pass it explicitly:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">service-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/ai-query/translate </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"question": "How many rows are in each table?", "database_name": "analytics"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="the-dashboard-experience">The Dashboard Experience<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#the-dashboard-experience" class="hash-link" aria-label="Direct link to The Dashboard Experience" title="Direct link to The Dashboard Experience">​</a></h2>
<p>The AI Query Console is built into the FoundryDB dashboard as a tab on every PostgreSQL and MySQL service. The workflow is straightforward:</p>
<ol>
<li>Type a question in the text field (or click one of the suggested examples).</li>
<li>Click <strong>Generate SQL</strong> (or press Cmd+Enter / Ctrl+Enter).</li>
<li>Review the generated SQL. Edit it if you want.</li>
<li>Click <strong>Run Query</strong> to execute.</li>
<li>View results in a paginated table with column headers, row counts, and execution time.</li>
</ol>
<p>The console tracks a local query history (up to 20 entries) so you can revisit previous questions without retyping them. If you modify the generated SQL before executing, a "Modified" badge appears so you can tell at a glance whether the query is the original or your edited version.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="example-questions-to-try">Example Questions to Try<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#example-questions-to-try" class="hash-link" aria-label="Direct link to Example Questions to Try" title="Direct link to Example Questions to Try">​</a></h3>
<p>For PostgreSQL services:</p>
<ul>
<li>"Show the top 10 largest tables by size"</li>
<li>"List active connections grouped by user"</li>
<li>"Show slow queries from the last hour"</li>
<li>"What indexes are unused?"</li>
<li>"Show table row counts for all user tables"</li>
</ul>
<p>For MySQL services:</p>
<ul>
<li>"Show the top 10 largest tables by size"</li>
<li>"List active connections grouped by user"</li>
<li>"Show the most frequently run queries"</li>
<li>"What indexes exist on each table?"</li>
<li>"Show table row counts for all tables"</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="api-reference">API Reference<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#api-reference" class="hash-link" aria-label="Direct link to API Reference" title="Direct link to API Reference">​</a></h2>
<p>Both endpoints require authentication and a running service.</p>
<table><thead><tr><th>Endpoint</th><th>Method</th><th>Description</th></tr></thead><tbody><tr><td><code>/managed-services/{serviceId}/ai-query/translate</code></td><td>POST</td><td>Translate natural language to SQL</td></tr><tr><td><code>/managed-services/{serviceId}/ai-query/execute</code></td><td>POST</td><td>Execute a read-only SQL query</td></tr></tbody></table>
<p><strong>Translate request body:</strong></p>
<table><thead><tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>question</code></td><td>string</td><td>Yes</td><td>Natural language question (max 1,000 characters)</td></tr><tr><td><code>database_name</code></td><td>string</td><td>No</td><td>Target database name (defaults to service default)</td></tr></tbody></table>
<p><strong>Execute request body:</strong></p>
<table><thead><tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>sql</code></td><td>string</td><td>Yes</td><td>SQL query to execute (must be read-only)</td></tr><tr><td><code>database_name</code></td><td>string</td><td>No</td><td>Target database name</td></tr></tbody></table>
<p><strong>Execute response:</strong></p>
<table><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>columns</code></td><td>string[]</td><td>Column names from the result set</td></tr><tr><td><code>rows</code></td><td>any[][]</td><td>Row data (each row is an array of values)</td></tr><tr><td><code>row_count</code></td><td>integer</td><td>Number of rows returned</td></tr><tr><td><code>execution_ms</code></td><td>integer</td><td>Query execution time in milliseconds</td></tr><tr><td><code>truncated</code></td><td>boolean</td><td>True if results were capped at 1,000 rows</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="error-handling">Error Handling<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#error-handling" class="hash-link" aria-label="Direct link to Error Handling" title="Direct link to Error Handling">​</a></h2>
<p>The API returns <a href="https://www.rfc-editor.org/rfc/rfc7807" target="_blank" rel="noopener noreferrer">RFC 7807</a> problem details for errors:</p>
<ul>
<li><strong>400</strong>: Empty question, question exceeding 1,000 characters, unsupported database type, service not in Running state, or blocked SQL.</li>
<li><strong>404</strong>: Service not found or access denied.</li>
<li><strong>501</strong>: AI Query feature not configured (missing Anthropic API key). Contact your administrator.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://docs.foundrydb.com/blog/ai-query-console-natural-language-sql#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<p>The AI Query Console is available on every PostgreSQL and MySQL service in FoundryDB. Open your service in the <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">dashboard</a>, navigate to the AI Query tab, and ask your first question.</p>
<p>If you prefer the API, check out the full <a href="https://docs.foundrydb.com/api/ai-query" target="_blank" rel="noopener noreferrer">AI Query documentation</a> for request and response schemas, or explore the feature with the <a href="https://docs.foundrydb.com/getting-started/cli" target="_blank" rel="noopener noreferrer">FoundryDB CLI</a>.</p>
<p>Don't have a FoundryDB account yet? <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">Sign up</a> and have a production-ready PostgreSQL or MySQL service running in under five minutes.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="sql" term="sql"/>
        <category label="natural-language" term="natural-language"/>
        <category label="query" term="query"/>
        <category label="postgresql" term="postgresql"/>
        <category label="mysql" term="mysql"/>
        <category label="mongodb" term="mongodb"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Migrate from SQL Server to PostgreSQL with Babelfish on FoundryDB]]></title>
        <id>https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql</id>
        <link href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Run your existing T-SQL queries and stored procedures on PostgreSQL without rewriting. FoundryDB's managed Babelfish provides dual-protocol access: TDS port 1433 for existing apps, PostgreSQL wire protocol for new ones.]]></summary>
        <content type="html"><![CDATA[<p>SQL Server licensing costs add up fast. Per-core pricing, Software Assurance renewals, and the looming end of extended support for older versions push teams to look for alternatives. PostgreSQL is the obvious destination, but rewriting thousands of stored procedures, converting T-SQL syntax, and updating every connection string is a project nobody wants to start.</p>
<p>Babelfish for PostgreSQL changes the equation. It adds a SQL Server wire-protocol layer (TDS) on top of PostgreSQL, so your existing applications connect to port 1433 and run T-SQL queries as before. No driver changes. No syntax rewrites. On FoundryDB, you get a fully managed Babelfish instance running on PostgreSQL 16 with backups, TLS, monitoring, and point-in-time recovery built in.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-babelfish">What Is Babelfish?<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#what-is-babelfish" class="hash-link" aria-label="Direct link to What Is Babelfish?" title="Direct link to What Is Babelfish?">​</a></h2>
<p>Babelfish is an open source extension for PostgreSQL, originally developed by AWS and now maintained by the community. It adds two capabilities to a standard PostgreSQL instance:</p>
<ol>
<li><strong>TDS wire protocol on port 1433.</strong> SQL Server clients (SSMS, sqlcmd, ADO.NET, JDBC with the SQL Server driver) connect to this port and interact with the database using their native protocol.</li>
<li><strong>T-SQL language support.</strong> Stored procedures, functions, triggers, and queries written in Transact-SQL execute on the PostgreSQL engine without modification.</li>
</ol>
<p>The underlying database is still PostgreSQL. You get full access to the PostgreSQL wire protocol on port 5432 in parallel, which means new services can use standard PostgreSQL drivers while legacy applications continue using TDS.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="dual-protocol-access">Dual-Protocol Access<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#dual-protocol-access" class="hash-link" aria-label="Direct link to Dual-Protocol Access" title="Direct link to Dual-Protocol Access">​</a></h2>
<p>Every Babelfish service on FoundryDB exposes two ports:</p>
<table><thead><tr><th>Port</th><th>Protocol</th><th>Use Case</th></tr></thead><tbody><tr><td><code>1433</code></td><td>TDS (SQL Server wire)</td><td>Existing .NET apps, SSMS, sqlcmd, JDBC SQL Server driver</td></tr><tr><td><code>5432</code></td><td>PostgreSQL</td><td>psql, pgAdmin, any PostgreSQL driver, new microservices</td></tr></tbody></table>
<p>Both ports point to the same data. A row inserted via TDS on port 1433 is immediately visible through a PostgreSQL query on port 5432. This dual-protocol model lets you migrate incrementally: keep the legacy app on TDS while building new features against the PostgreSQL interface.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="provisioning-a-babelfish-service">Provisioning a Babelfish Service<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#provisioning-a-babelfish-service" class="hash-link" aria-label="Direct link to Provisioning a Babelfish Service" title="Direct link to Provisioning a Babelfish Service">​</a></h2>
<p>A single API call provisions a production-ready Babelfish instance. FoundryDB handles the custom PostgreSQL 16 binary, the Babelfish extension initialization, TLS certificates, and firewall rules.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Via CLI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> legacy-crm </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> mssql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">4.8</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-4 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">100</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-tier maxiops </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> se-sto1</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Via API</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "name": "legacy-crm",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_type": "mssql",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "version": "4.8",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-4",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_size_gb": 100,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_tier": "maxiops",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "se-sto1"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Under the hood, FoundryDB provisions a VM from a pre-built Packer template that includes the Babelfish-patched PostgreSQL 16 binary at <code>/opt/babelfish/</code>. The agent initializes the cluster with data checksums enabled, loads the <code>babelfishpg_tds</code> extension, creates the internal <code>babelfish_db</code> database, and calls <code>sys.initialize_babelfish</code> to set up the T-SQL catalog. The TDS listener starts on port 1433 automatically.</p>
<p>Provisioning typically completes in under five minutes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="connecting-your-application">Connecting Your Application<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#connecting-your-application" class="hash-link" aria-label="Direct link to Connecting Your Application" title="Direct link to Connecting Your Application">​</a></h2>
<p>Once the service is running, retrieve your credentials and DNS hostname from the FoundryDB dashboard or API.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="sql-server-clients-tds-port-1433">SQL Server Clients (TDS, Port 1433)<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#sql-server-clients-tds-port-1433" class="hash-link" aria-label="Direct link to SQL Server Clients (TDS, Port 1433)" title="Direct link to SQL Server Clients (TDS, Port 1433)">​</a></h3>
<p>Use any SQL Server driver or tool. The connection looks identical to connecting to a real SQL Server instance.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># sqlcmd</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">sqlcmd </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-S</span><span class="token plain"> your-service.db.foundrydb.com,1433 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-U</span><span class="token plain"> app_user </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-P</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'your-password'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-Q</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"SELECT @@VERSION"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># .NET / ADO.NET connection string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">Server</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">your-service.db.foundrydb.com,1433</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">Database</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">defaultdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain">User </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">Id</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">app_user</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">Password</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">your-password</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">Encrypt</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">TrustServerCertificate</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># JDBC (SQL Server driver)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">jdbc:sqlserver://your-service.db.foundrydb.com:1433</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">databaseName</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">defaultdb</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">user</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">app_user</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">password</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">your-password</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">encrypt</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="postgresql-clients-port-5432">PostgreSQL Clients (Port 5432)<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#postgresql-clients-port-5432" class="hash-link" aria-label="Direct link to PostgreSQL Clients (Port 5432)" title="Direct link to PostgreSQL Clients (Port 5432)">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token assign-left variable" style="color:rgb(156, 220, 254)">PGPASSWORD</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">'your-password'</span><span class="token plain"> psql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"host=your-service.db.foundrydb.com user=app_user dbname=defaultdb sslmode=verify-full"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="sql-server-management-studio-ssms">SQL Server Management Studio (SSMS)<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#sql-server-management-studio-ssms" class="hash-link" aria-label="Direct link to SQL Server Management Studio (SSMS)" title="Direct link to SQL Server Management Studio (SSMS)">​</a></h3>
<p>Open SSMS and enter:</p>
<ul>
<li><strong>Server name:</strong> <code>your-service.db.foundrydb.com,1433</code></li>
<li><strong>Authentication:</strong> SQL Server Authentication</li>
<li><strong>Login:</strong> your database user</li>
<li><strong>Password:</strong> your database password</li>
</ul>
<p>Check "Encrypt connection" in the connection properties. SSMS will connect over TDS and display the database objects as it would for any SQL Server instance.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-t-sql-syntax-works">What T-SQL Syntax Works<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#what-t-sql-syntax-works" class="hash-link" aria-label="Direct link to What T-SQL Syntax Works" title="Direct link to What T-SQL Syntax Works">​</a></h2>
<p>Babelfish 4.x supports a broad subset of T-SQL. For most CRUD applications, stored procedure logic, and reporting queries, the migration is straightforward.</p>
<p><strong>Supported:</strong></p>
<ul>
<li>DML: <code>SELECT</code>, <code>INSERT</code>, <code>UPDATE</code>, <code>DELETE</code>, <code>MERGE</code></li>
<li>Programmability: <code>CREATE PROCEDURE</code>, <code>CREATE FUNCTION</code>, <code>CREATE TRIGGER</code></li>
<li>SQL Server data types: <code>NVARCHAR</code>, <code>DATETIME</code>, <code>UNIQUEIDENTIFIER</code>, <code>BIT</code>, <code>MONEY</code>, and others</li>
<li>System views: partial <code>sys.</code> catalog emulation, <code>INFORMATION_SCHEMA</code> views</li>
<li>Session settings: <code>SET NOCOUNT ON</code>, <code>SET ANSI_NULLS ON</code>, and other common <code>SET</code> options</li>
</ul>
<p><strong>Not supported:</strong></p>
<table><thead><tr><th>Feature</th><th>Status</th></tr></thead><tbody><tr><td>SQL Server Agent jobs</td><td>Not supported</td></tr><tr><td>Linked servers</td><td>Not supported</td></tr><tr><td>CLR integration (.NET assemblies)</td><td>Not supported</td></tr><tr><td>Full-text search (<code>CONTAINS</code>, <code>FREETEXT</code>)</td><td>Not supported</td></tr><tr><td><code>OPENROWSET</code> / <code>OPENDATASOURCE</code></td><td>Not supported</td></tr><tr><td>Distributed transactions (MSDTC)</td><td>Not supported</td></tr><tr><td>Change Data Capture (CDC)</td><td>Not supported</td></tr><tr><td><code>FOR XML</code> clauses</td><td>Limited support</td></tr><tr><td>Spatial data types (<code>GEOMETRY</code>, <code>GEOGRAPHY</code>)</td><td>Limited support</td></tr></tbody></table>
<p>If your application uses SQL Server Agent for scheduled jobs, replace those with cron, a task scheduler like Celery, or an external orchestrator. For full-text search, consider pairing your Babelfish service with an OpenSearch instance on FoundryDB.</p>
<p>For the complete compatibility matrix, refer to the <a href="https://babelfishpg.org/docs/usage/limitations-of-babelfish/" target="_blank" rel="noopener noreferrer">official Babelfish documentation</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="migration-steps">Migration Steps<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#migration-steps" class="hash-link" aria-label="Direct link to Migration Steps" title="Direct link to Migration Steps">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-assess-your-t-sql-codebase">1. Assess Your T-SQL Codebase<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#1-assess-your-t-sql-codebase" class="hash-link" aria-label="Direct link to 1. Assess Your T-SQL Codebase" title="Direct link to 1. Assess Your T-SQL Codebase">​</a></h3>
<p>Use the <a href="https://babelfishpg.org/docs/usage/babelfish-compass/" target="_blank" rel="noopener noreferrer">Babelfish Compass</a> tool to analyze your existing SQL Server database. It scans DDL scripts, stored procedures, and functions, then reports which constructs are supported, partially supported, or unsupported.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Export your schema from SQL Server</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">sqlcmd </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-S</span><span class="token plain"> old-server </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-U</span><span class="token plain"> sa </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-Q</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"EXEC sp_generate_inserts"</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-o</span><span class="token plain"> schema.sql</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Run Babelfish Compass against the DDL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">java</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-jar</span><span class="token plain"> BabelfishCompass.jar schema.sql</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-provision-and-load-schema">2. Provision and Load Schema<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#2-provision-and-load-schema" class="hash-link" aria-label="Direct link to 2. Provision and Load Schema" title="Direct link to 2. Provision and Load Schema">​</a></h3>
<p>Create your FoundryDB Babelfish service, then connect via TDS and run your DDL scripts directly.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">sqlcmd </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-S</span><span class="token plain"> your-service.db.foundrydb.com,1433 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-U</span><span class="token plain"> app_user </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-P</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'your-password'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-i</span><span class="token plain"> schema.sql</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-migrate-data">3. Migrate Data<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#3-migrate-data" class="hash-link" aria-label="Direct link to 3. Migrate Data" title="Direct link to 3. Migrate Data">​</a></h3>
<p>For initial data loads, export from SQL Server using <code>bcp</code> or a custom ETL pipeline, then import via the same TDS connection. For smaller datasets, <code>INSERT ... SELECT</code> over linked tooling works fine.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4-update-connection-strings">4. Update Connection Strings<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#4-update-connection-strings" class="hash-link" aria-label="Direct link to 4. Update Connection Strings" title="Direct link to 4. Update Connection Strings">​</a></h3>
<p>Point your application's SQL Server connection string to the FoundryDB hostname. Since the TDS protocol is the same, most applications require only a hostname change.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="5-validate-with-both-protocols">5. Validate with Both Protocols<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#5-validate-with-both-protocols" class="hash-link" aria-label="Direct link to 5. Validate with Both Protocols" title="Direct link to 5. Validate with Both Protocols">​</a></h3>
<p>Run your application test suite against the TDS endpoint. In parallel, connect via PostgreSQL on port 5432 to verify that the data is accessible from both protocols.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="backups-and-recovery">Backups and Recovery<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#backups-and-recovery" class="hash-link" aria-label="Direct link to Backups and Recovery" title="Direct link to Backups and Recovery">​</a></h2>
<p>Babelfish on FoundryDB uses pgBackRest for continuous WAL archiving. Point-in-time recovery (PITR) lets you restore to any second within the retention window.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups/restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "restore_point": "2026-04-05T14:30:00Z",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "target_service_name": "crm-restored"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="postgresql-configuration">PostgreSQL Configuration<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#postgresql-configuration" class="hash-link" aria-label="Direct link to PostgreSQL Configuration" title="Direct link to PostgreSQL Configuration">​</a></h2>
<p>Since Babelfish runs on PostgreSQL 16, you tune it like any PostgreSQL instance. Adjust <code>shared_buffers</code>, <code>max_connections</code>, and other parameters through the FoundryDB configuration API.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PATCH </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/configuration </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "parameters": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "max_connections": "200",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "shared_buffers": "2GB"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="feature-matrix">Feature Matrix<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#feature-matrix" class="hash-link" aria-label="Direct link to Feature Matrix" title="Direct link to Feature Matrix">​</a></h2>
<p>FoundryDB's Babelfish service includes the same operational features as other engines on the platform:</p>
<table><thead><tr><th>Feature</th><th>Supported</th></tr></thead><tbody><tr><td>High Availability</td><td>Yes</td></tr><tr><td>Point-in-Time Recovery</td><td>Yes</td></tr><tr><td>TLS / SSL</td><td>Yes</td></tr><tr><td>Connection Pooling</td><td>Yes</td></tr><tr><td>Auto Failover</td><td>Yes</td></tr><tr><td>Monitoring and Alerts</td><td>Yes</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="when-babelfish-is-the-right-choice">When Babelfish Is the Right Choice<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#when-babelfish-is-the-right-choice" class="hash-link" aria-label="Direct link to When Babelfish Is the Right Choice" title="Direct link to When Babelfish Is the Right Choice">​</a></h2>
<p>Babelfish works best for applications where the T-SQL surface area is standard CRUD, reporting, and stored procedure logic. If your codebase avoids CLR integration, linked servers, and SQL Server Agent, the migration path is clean.</p>
<p>For applications that depend heavily on SQL Server-specific features, a full PostgreSQL rewrite may still be the better long-term investment. Babelfish gives you a middle ground: move off SQL Server licensing today, then gradually shift T-SQL code to native PostgreSQL syntax at your own pace.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://docs.foundrydb.com/blog/migrate-sql-server-babelfish-postgresql#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<p>Provision a Babelfish service on FoundryDB and run your T-SQL workload against it. The dual-protocol access means you can test without touching your application code.</p>
<ul>
<li><a href="https://docs.foundrydb.com/databases/mssql" target="_blank" rel="noopener noreferrer">Babelfish documentation on FoundryDB</a></li>
<li><a href="https://docs.foundrydb.com/api" target="_blank" rel="noopener noreferrer">API reference</a></li>
<li><a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">Create a free account</a></li>
</ul>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="babelfish" term="babelfish"/>
        <category label="sql-server" term="sql-server"/>
        <category label="mssql" term="mssql"/>
        <category label="migration" term="migration"/>
        <category label="t-sql" term="t-sql"/>
        <category label="postgresql" term="postgresql"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Never Lose Data: Automated Backups and Point-in-Time Recovery on FoundryDB]]></title>
        <id>https://docs.foundrydb.com/blog/automated-backups-pitr-guide</id>
        <link href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How FoundryDB handles backups across all database engines. Configure schedules, test restores, and recover to any second with PITR.]]></summary>
        <content type="html"><![CDATA[<p>Every managed database service on FoundryDB gets automated backups from the moment it starts running. There is nothing to configure, no S3 bucket to provision, and no cron job to maintain. Backups run daily, are encrypted before they leave the server, and are stored in object storage across a separate availability zone.</p>
<p>But automated daily backups are only half the story. For PostgreSQL, MySQL, and MongoDB, FoundryDB continuously archives write-ahead logs (WAL), binary logs (binlog), or oplogs to enable point-in-time recovery (PITR). This means you can restore to any specific second within a 7-day window, not just to the last daily snapshot.</p>
<p>This post covers how backups work across all engines, how to trigger and restore them, and how to use PITR to recover from the kind of mistakes that daily snapshots cannot fix.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-backups-work-per-engine">How Backups Work Per Engine<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#how-backups-work-per-engine" class="hash-link" aria-label="Direct link to How Backups Work Per Engine" title="Direct link to How Backups Work Per Engine">​</a></h2>
<p>FoundryDB uses the native backup tooling for each database engine. This is intentional. Native tools are the most reliable, best-tested path for each engine, and they integrate with the engine's own consistency guarantees.</p>
<table><thead><tr><th>Engine</th><th>Backup tool</th><th>PITR support</th><th>Continuous archiving</th></tr></thead><tbody><tr><td>PostgreSQL</td><td>pgBackRest</td><td>Yes, any second</td><td>WAL archiving</td></tr><tr><td>MySQL</td><td>mysqldump + binlog</td><td>Yes, any second</td><td>Binlog archiving</td></tr><tr><td>MongoDB</td><td>mongodump + oplog</td><td>Yes, any second</td><td>Oplog archiving</td></tr><tr><td>Valkey</td><td>RDB snapshots</td><td>Daily snapshots only</td><td>AOF (append-only file)</td></tr><tr><td>Kafka</td><td>Topic snapshots</td><td>No</td><td>N/A</td></tr></tbody></table>
<p>For PostgreSQL, pgBackRest handles full and incremental backups with built-in verification, parallelism, and encryption. WAL segments are archived continuously to S3, so the recovery window extends from the last full backup to the most recent archived WAL segment.</p>
<p>For MySQL, a logical dump captures the schema and data, while binlog archiving captures every write operation between dumps. Restore replays the dump, then applies binlogs up to the target timestamp.</p>
<p>For MongoDB, mongodump captures a consistent snapshot of all collections, and oplog archiving captures the stream of write operations. PITR replays the oplog from the dump point to the target time.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="backup-encryption">Backup Encryption<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#backup-encryption" class="hash-link" aria-label="Direct link to Backup Encryption" title="Direct link to Backup Encryption">​</a></h2>
<p>All backups are encrypted with AES-256-GCM before leaving the database server. Each backup gets a unique encryption key. Keys rotate automatically every 90 days. Object storage adds a second layer of server-side encryption for defense in depth.</p>
<p>You do not need to configure encryption. It is always on.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Verify encryption status on any backup</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">backup_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> jq </span><span class="token string" style="color:rgb(206, 145, 120)">'{encrypted: .encryption_enabled, algorithm: .encryption_algorithm}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token property">"encrypted"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"algorithm"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"AES-256-GCM"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="triggering-an-on-demand-backup">Triggering an On-Demand Backup<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#triggering-an-on-demand-backup" class="hash-link" aria-label="Direct link to Triggering an On-Demand Backup" title="Direct link to Triggering an On-Demand Backup">​</a></h2>
<p>Automated backups run daily, but you can trigger a manual backup at any time. This is useful before a risky schema migration, a bulk data load, or a major application deployment.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"backup_type": "manual"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"bkp_m7x2k9"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"backup_type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"manual"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"in_progress"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-04-06T15:30:00Z"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Manual backups are retained until you explicitly delete them. Automated backups follow the 7-day retention policy.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="listing-backups">Listing Backups<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#listing-backups" class="hash-link" aria-label="Direct link to Listing Backups" title="Direct link to Listing Backups">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"backups"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"bkp_abc123"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"backup_type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"automated"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"completed"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"size_bytes"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1073741824</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-04-06T02:00:00Z"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"bkp_m7x2k9"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"backup_type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"manual"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"completed"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"size_bytes"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1073741824</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-04-06T15:30:00Z"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="point-in-time-recovery">Point-in-Time Recovery<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#point-in-time-recovery" class="hash-link" aria-label="Direct link to Point-in-Time Recovery" title="Direct link to Point-in-Time Recovery">​</a></h2>
<p>Daily backups protect against hardware failure and data corruption. PITR protects against the other kind of disaster: human error. Someone runs <code>DELETE FROM orders</code> without a <code>WHERE</code> clause at 14:32:17. With daily backups, you lose everything since the last snapshot. With PITR, you restore to 14:32:16 and lose nothing.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-pitr-works">How PITR Works<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#how-pitr-works" class="hash-link" aria-label="Direct link to How PITR Works" title="Direct link to How PITR Works">​</a></h3>
<p>PITR combines two pieces: a base backup (the most recent full snapshot) and a continuous stream of change records (WAL segments, binlogs, or oplog entries). To restore to a specific point in time, FoundryDB restores the base backup and then replays the change stream up to the exact target timestamp.</p>
<p>The PITR window on FoundryDB is 7 days. WAL, binlog, and oplog archives are retained for 7 days, so you can restore to any second within that window.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="restoring-to-a-specific-time">Restoring to a Specific Time<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#restoring-to-a-specific-time" class="hash-link" aria-label="Direct link to Restoring to a Specific Time" title="Direct link to Restoring to a Specific Time">​</a></h3>
<p>Restoring always creates a new service. Your existing service keeps running undisturbed.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups/restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "restore_point": "2026-04-06T14:32:16Z",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "target_service_name": "orders-db-restored",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "se-sto1"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 restored service provisions a new VM, restores the base backup, replays the change stream to the specified timestamp, and starts accepting connections. Depending on database size, this takes 5 to 30 minutes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="restoring-from-a-specific-backup">Restoring from a Specific Backup<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#restoring-from-a-specific-backup" class="hash-link" aria-label="Direct link to Restoring from a Specific Backup" title="Direct link to Restoring from a Specific Backup">​</a></h3>
<p>If you want to restore from a particular daily or manual backup rather than a point in time:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">backup_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "target_service_name": "orders-db-from-backup",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "se-sto1"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-restore-progress">Monitoring Restore Progress<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#monitoring-restore-progress" class="hash-link" aria-label="Direct link to Monitoring Restore Progress" title="Direct link to Monitoring Restore Progress">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">restored_service_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> jq </span><span class="token string" style="color:rgb(206, 145, 120)">'{name: .name, status: .status}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Watch the <code>status</code> field transition from <code>pending</code> to <code>provisioning</code> to <code>running</code>. Once the status is <code>running</code>, your restored database is ready to accept connections.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="testing-your-backups">Testing Your Backups<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#testing-your-backups" class="hash-link" aria-label="Direct link to Testing Your Backups" title="Direct link to Testing Your Backups">​</a></h2>
<p>A backup you have never restored is a backup you cannot trust. FoundryDB makes it easy to test restores because every restore creates a new, independent service. There is no risk to your production data.</p>
<p>A simple monthly practice:</p>
<ol>
<li>Trigger a manual backup of your production service.</li>
<li>Restore it to a new service with a test name.</li>
<li>Connect to the restored service and run validation queries against your data.</li>
<li>Delete the test service when you are done.</li>
</ol>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># 1. Trigger manual backup</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"backup_type": "manual"}'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># 2. Restore to a test service (use the backup ID from step 1)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">backup_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "target_service_name": "monthly-restore-test",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "se-sto1"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># 3. Validate data on the restored service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">PGPASSWORD</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">restored_pass psql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"host=monthly-restore-test.foundrydb.com user=app_user dbname=defaultdb sslmode=verify-full"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-c</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"SELECT count(*) FROM orders;"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># 4. Clean up</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> DELETE </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">restored_service_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This costs only the compute time for the restored service (minutes, not hours) and gives you confidence that your backups are actually recoverable.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="retention-policies">Retention Policies<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#retention-policies" class="hash-link" aria-label="Direct link to Retention Policies" title="Direct link to Retention Policies">​</a></h2>
<table><thead><tr><th>Backup type</th><th>Retention</th></tr></thead><tbody><tr><td>Automated daily</td><td>7 days</td></tr><tr><td>Manual</td><td>Until deleted</td></tr><tr><td>WAL / binlog / oplog (PITR window)</td><td>7 days</td></tr></tbody></table>
<p>Manual backups are never automatically deleted. If you create manual backups before deployments, remember to clean up old ones periodically:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> DELETE </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">backup_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="disaster-recovery-checklist">Disaster Recovery Checklist<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#disaster-recovery-checklist" class="hash-link" aria-label="Direct link to Disaster Recovery Checklist" title="Direct link to Disaster Recovery Checklist">​</a></h2>
<p>Before you need to restore in a real incident, prepare now:</p>
<ol>
<li><strong>Test restores regularly.</strong> Restore to a new service and verify your data. Monthly is a good cadence.</li>
<li><strong>Verify PITR is active.</strong> Check your service metrics to confirm WAL/binlog/oplog archiving is running continuously.</li>
<li><strong>Document your RTO and RPO.</strong> Know how long a restore takes for your database size and how much data loss you can tolerate.</li>
<li><strong>Take manual backups before risky operations.</strong> Schema migrations, bulk deletes, and version upgrades all warrant a pre-change backup.</li>
<li><strong>Keep your allowed_cidrs updated.</strong> A restored service inherits the source service's network rules. Make sure your application can connect.</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-next">What's Next<a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide#whats-next" class="hash-link" aria-label="Direct link to What's Next" title="Direct link to What's Next">​</a></h2>
<p>Backups and PITR are available on every FoundryDB service with no additional configuration. If you are running a database that matters, take 10 minutes to test a restore today. The best time to discover a problem with your backup strategy is before you need it.</p>
<p>Read the full <a href="https://docs.foundrydb.com/operations/backups">Backups and Restore documentation</a> for API details and per-engine specifics. If you are not yet on FoundryDB, <a href="https://docs.foundrydb.com/getting-started/quick-start">create your first service</a> and see automated backups working within minutes.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="backups" term="backups"/>
        <category label="pitr" term="pitr"/>
        <category label="disaster-recovery" term="disaster-recovery"/>
        <category label="postgresql" term="postgresql"/>
        <category label="mysql" term="mysql"/>
        <category label="mongodb" term="mongodb"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Zero-Downtime Database Upgrades with Blue-Green Deployments]]></title>
        <id>https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments</id>
        <link href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Upgrade your database version without any downtime using FoundryDB's blue-green deployment strategy. Validate before switching, rollback if needed.]]></summary>
        <content type="html"><![CDATA[<p>Database upgrades are the kind of task that sounds simple until you remember what is at stake. A botched upgrade means downtime, and downtime means lost revenue, broken trust, and on-call engineers reading logs at 3 AM. Rolling updates help, but they still mutate your live environment in place. Blue-green deployments take a fundamentally different approach: build the new environment first, verify it works, then switch traffic over in one atomic step.</p>
<p>FoundryDB supports blue-green deployments as a first-class maintenance operation. You can validate prerequisites, provision a parallel green environment, let replication sync the data, and switchover when you are confident. If something goes wrong before or after the switch, you roll back.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-blue-green-instead-of-rolling-updates">Why Blue-Green Instead of Rolling Updates<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#why-blue-green-instead-of-rolling-updates" class="hash-link" aria-label="Direct link to Why Blue-Green Instead of Rolling Updates" title="Direct link to Why Blue-Green Instead of Rolling Updates">​</a></h2>
<p>Rolling updates upgrade one node at a time within your existing cluster. They work well for minor version bumps and configuration changes, and FoundryDB supports them with pause/resume controls. But rolling updates have limitations:</p>
<table><thead><tr><th></th><th>Rolling Update</th><th>Blue-Green Deployment</th></tr></thead><tbody><tr><td><strong>Downtime</strong></td><td>Brief failover (~60s) during primary promotion</td><td>Zero, DNS cutover is atomic</td></tr><tr><td><strong>Validation</strong></td><td>No pre-switch validation on the target version</td><td>Full validation before switchover</td></tr><tr><td><strong>Rollback</strong></td><td>Must re-upgrade nodes already changed</td><td>Instant, traffic returns to original environment</td></tr><tr><td><strong>Resource cost</strong></td><td>No extra VMs</td><td>Temporary second environment (cleaned up after)</td></tr><tr><td><strong>Best for</strong></td><td>Config changes, minor version patches</td><td>Minor version upgrades, VM replacement, zero-downtime maintenance</td></tr></tbody></table>
<p>The tradeoff is straightforward. Blue-green costs more during the transition (you are running two environments), but gives you a safety net that rolling updates cannot match. For production databases where even a 60-second failover is unacceptable, blue-green is the right choice.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-works-on-foundrydb">How It Works on FoundryDB<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#how-it-works-on-foundrydb" class="hash-link" aria-label="Direct link to How It Works on FoundryDB" title="Direct link to How It Works on FoundryDB">​</a></h2>
<p>A blue-green deployment on FoundryDB follows a six-state lifecycle:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">Running → BlueGreenCreating → BlueGreenSyncing → BlueGreenReady → BlueGreenSwitching → BlueGreenCleaning → Running</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<ol>
<li><strong>Creating.</strong> FoundryDB provisions a new "green" VM with the target database version. Same compute plan, same storage tier, same configuration as your live "blue" environment.</li>
<li><strong>Syncing.</strong> Streaming replication starts from blue to green. All writes to the blue environment are continuously replicated to the green environment.</li>
<li><strong>Ready.</strong> Once replication lag drops below your configured threshold (default: 5000 ms), the deployment enters the <code>ready</code> state. You can now inspect the green environment and run validation queries.</li>
<li><strong>Switching.</strong> You trigger the switchover. DNS records update to point to the green environment. This is atomic: your connection strings do not change.</li>
<li><strong>Cleaning.</strong> The old blue environment is retained briefly for rollback, then automatically cleaned up.</li>
<li><strong>Running.</strong> The service returns to normal operation on the new environment.</li>
</ol>
<p>At any point before the switchover completes, you can roll back. Traffic returns to the original blue environment and the green environment is torn down.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-validate-prerequisites">Step 1: Validate Prerequisites<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#step-1-validate-prerequisites" class="hash-link" aria-label="Direct link to Step 1: Validate Prerequisites" title="Direct link to Step 1: Validate Prerequisites">​</a></h2>
<p>Before starting a deployment, check whether your service supports blue-green for the target version. The validate endpoint returns a clear pass/fail result with specific error messages if something blocks the deployment.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/blue-green/validate </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"target_version": "17.7"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>A successful validation returns:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"valid"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"warnings"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"errors"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"current_version"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"17.3"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"target_version"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"17.7"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"database_type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"upgrade_type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"minor"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"replication_mode"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"streaming"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 validation checks four things: that your service is in <code>Running</code> state, that no other maintenance operation is already active, that the version increment is sequential (no skipping, e.g., 15 to 17), and that the database engine supports the deployment type.</p>
<p><strong>Known limitation:</strong> Major version blue-green (e.g., PostgreSQL 16 to 17) is not yet supported for PostgreSQL and MySQL. Streaming replication cannot work across major versions due to WAL/binlog format incompatibility. Logical replication support is planned for a future release. For major version upgrades on these engines, use the in-place <code>pg_upgrade</code> or <code>mysql_upgrade</code> paths instead.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-create-the-deployment">Step 2: Create the Deployment<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#step-2-create-the-deployment" class="hash-link" aria-label="Direct link to Step 2: Create the Deployment" title="Direct link to Step 2: Create the Deployment">​</a></h2>
<p>Once validation passes, create the blue-green deployment:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/blue-green </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "target_version": "17.7",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "replication_lag_ms": 5000</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response returns a deployment ID and confirms the service is transitioning:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"6fa85f64-5717-4562-b3fc-2c963f66afa6"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"service_id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"a1b2c3d4-..."</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"in_progress"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"target_version"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"17.7"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"replication_lag_ms"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">5000</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-04-06T14:30:00Z"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>replication_lag_ms</code> parameter controls how close the green environment must be to the blue environment before the deployment is considered ready for switchover. Lower values mean tighter consistency but may take longer to stabilize under heavy write loads. The minimum is 100 ms.</p>
<p>You can also schedule deployments for a future maintenance window by adding <code>scheduled_at</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/blue-green </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "target_version": "17.7",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "replication_lag_ms": 1000,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "scheduled_at": "2026-04-10T02:00:00Z"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="step-3-monitor-and-validate">Step 3: Monitor and Validate<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#step-3-monitor-and-validate" class="hash-link" aria-label="Direct link to Step 3: Monitor and Validate" title="Direct link to Step 3: Monitor and Validate">​</a></h2>
<p>Poll the deployment status to track replication progress:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/blue-green/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">deployment-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Once the status shows <code>ready</code> (the <code>BlueGreenReady</code> state), the green environment is fully synced. This is your window to run any validation you need: connect to the green service, run test queries, verify that your application logic works against the new version.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-switchover">Step 4: Switchover<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#step-4-switchover" class="hash-link" aria-label="Direct link to Step 4: Switchover" title="Direct link to Step 4: Switchover">​</a></h2>
<p>When you are satisfied that the green environment is correct, trigger the switchover:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PUT </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/blue-green/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">deployment-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/switchover</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 service must be in <code>BlueGreenReady</code> state. If it is not (for example, if replication has not caught up), the API returns a <code>409 Conflict</code> with the current state.</p>
<p>After switchover, DNS records are updated to point to the green environment. Your application's connection strings remain the same. The old blue environment is retained briefly, then cleaned up automatically.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="rollback">Rollback<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#rollback" class="hash-link" aria-label="Direct link to Rollback" title="Direct link to Rollback">​</a></h2>
<p>If something goes wrong before or after the switchover (but before cleanup completes), roll back:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PUT </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/blue-green/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">deployment-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/rollback</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Traffic re-points to the original blue environment and the green environment is torn down. Rollback is not available after the deployment reaches <code>completed</code> or <code>cancelled</code> status.</p>
<p>To cancel a deployment that has not yet switched over (for example, if you decide not to proceed during the validation phase), use the cancel endpoint instead:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> DELETE </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/blue-green/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">deployment-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This cleans up the green environment and returns the service to <code>Running</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="when-to-use-each-strategy">When to Use Each Strategy<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#when-to-use-each-strategy" class="hash-link" aria-label="Direct link to When to Use Each Strategy" title="Direct link to When to Use Each Strategy">​</a></h2>
<p><strong>Use rolling updates when:</strong></p>
<ul>
<li>Applying configuration changes across your cluster</li>
<li>Performing minor version patches on multi-node services</li>
<li>You can tolerate a brief failover (~60 seconds) during primary promotion</li>
<li>Minimizing temporary resource cost matters</li>
</ul>
<p><strong>Use blue-green deployments when:</strong></p>
<ul>
<li>Zero downtime is a hard requirement</li>
<li>You want to validate the target version before committing</li>
<li>You need the ability to roll back instantly after switchover</li>
<li>You are performing same-version maintenance (VM replacement, OS patching via a fresh environment)</li>
</ul>
<p>Both strategies are available for the same service. You can use rolling updates for routine patches and reserve blue-green for higher-stakes upgrades.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://docs.foundrydb.com/blog/zero-downtime-blue-green-deployments#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<p>Blue-green deployments are available on all FoundryDB database engines that support streaming replication: PostgreSQL, Valkey, MongoDB, and Kafka. Start by validating your target version, then create your first blue-green deployment.</p>
<p>Read the full <a href="https://docs.foundrydb.com/operations/maintenance" target="_blank" rel="noopener noreferrer">Maintenance &amp; Upgrades documentation</a> for details on maintenance windows, rolling updates, and version upgrade paths. Or <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">create a free FoundryDB account</a> and try it on a test service.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="blue-green" term="blue-green"/>
        <category label="zero-downtime" term="zero-downtime"/>
        <category label="upgrades" term="upgrades"/>
        <category label="deployment" term="deployment"/>
        <category label="maintenance" term="maintenance"/>
        <category label="devops" term="devops"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Building a RAG Pipeline with PostgreSQL pgvector and Kafka on FoundryDB]]></title>
        <id>https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka</id>
        <link href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Build a production RAG pipeline using PostgreSQL pgvector for vector storage, Kafka for document ingestion, and Valkey for caching on FoundryDB.]]></summary>
        <content type="html"><![CDATA[<p>Retrieval-Augmented Generation (RAG) has become the standard approach for grounding LLMs in factual, up-to-date data. Instead of fine-tuning a model on your corpus (expensive, slow, stale within weeks), you retrieve relevant context at query time and feed it to the LLM alongside the user's question.</p>
<p>In 2026, RAG is no longer experimental. It powers customer support bots, internal knowledge search, legal document analysis, and code assistants at thousands of companies. The architecture has stabilized around a common pattern: ingest documents, generate embeddings, store vectors, retrieve at query time. What varies is how well you operate the infrastructure underneath.</p>
<p>This post walks through building a production RAG pipeline on FoundryDB using PostgreSQL with pgvector, Kafka for document ingestion, and Valkey for result caching.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="architecture-overview">Architecture Overview<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#architecture-overview" class="hash-link" aria-label="Direct link to Architecture Overview" title="Direct link to Architecture Overview">​</a></h2>
<p>The pipeline has four stages:</p>
<ol>
<li><strong>Ingest</strong>: Documents arrive via Kafka topics. Producers can be web scrapers, file upload handlers, or webhook receivers.</li>
<li><strong>Embed</strong>: A consumer reads from Kafka, chunks the documents, calls an embedding API (OpenAI, Cohere, or a local model), and writes vectors to PostgreSQL.</li>
<li><strong>Store</strong>: PostgreSQL with pgvector stores embeddings alongside metadata. HNSW indexes enable sub-millisecond approximate nearest neighbor search.</li>
<li><strong>Query</strong>: At query time, the user's question is embedded, similar vectors are retrieved from PostgreSQL, and the results (plus the original question) are sent to the LLM. Valkey caches frequent queries to reduce latency and cost.</li>
</ol>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">┌──────────┐    ┌───────┐    ┌────────────────────┐    ┌────────┐</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">│ Documents├───►│ Kafka ├───►│ PostgreSQL pgvector │◄───┤ App/LLM│</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">└──────────┘    └───────┘    └────────────────────┘    └───┬────┘</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                                                           │</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                                                      ┌────▼────┐</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                                                      │  Valkey  │</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                                                      │ (cache)  │</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                                                      └─────────┘</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="deploying-the-services">Deploying the Services<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#deploying-the-services" class="hash-link" aria-label="Direct link to Deploying the Services" title="Direct link to Deploying the Services">​</a></h2>
<p>Create all three services using the FoundryDB CLI. Each service is production-ready with TLS, automated backups, and monitoring out of the box.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># PostgreSQL with pgvector enabled</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> rag-vectors </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> postgresql </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">17</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-4 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">100</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-tier maxiops </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--preset</span><span class="token plain"> pgvector</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Kafka for document ingestion</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> rag-ingest </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> kafka </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">3.9</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-4 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">200</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Valkey for query result caching</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> rag-cache </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> valkey </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">8.1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-2 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">20</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>--preset pgvector</code> flag automatically enables the pgvector extension on your PostgreSQL instance. All three services deploy in the same EU zone, keeping inter-service latency under 1ms.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="setting-up-the-vector-store">Setting Up the Vector Store<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#setting-up-the-vector-store" class="hash-link" aria-label="Direct link to Setting Up the Vector Store" title="Direct link to Setting Up the Vector Store">​</a></h2>
<p>Once PostgreSQL is running, create your embeddings table and index. The schema stores the embedding vector, the original text chunk, and metadata for filtering.</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Enable pgvector (already done if you used the pgvector preset)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> EXTENSION </span><span class="token keyword" style="color:rgb(86, 156, 214)">IF</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">NOT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">EXISTS</span><span class="token plain"> vector</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Embeddings table: 1536 dimensions for OpenAI text-embedding-3-small</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">TABLE</span><span class="token plain"> embeddings </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    id          </span><span class="token keyword" style="color:rgb(86, 156, 214)">bigint</span><span class="token plain"> GENERATED ALWAYS </span><span class="token keyword" style="color:rgb(86, 156, 214)">AS</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">IDENTITY</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">KEY</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    content     </span><span class="token keyword" style="color:rgb(86, 156, 214)">text</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">NOT</span><span class="token plain"> </span><span class="token boolean">NULL</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    metadata    jsonb </span><span class="token operator" style="color:rgb(212, 212, 212)">NOT</span><span class="token plain"> </span><span class="token boolean">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">DEFAULT</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{}'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    embedding   vector</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token number" style="color:rgb(181, 206, 168)">1536</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">NOT</span><span class="token plain"> </span><span class="token boolean">NULL</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    created_at  timestamptz </span><span class="token operator" style="color:rgb(212, 212, 212)">NOT</span><span class="token plain"> </span><span class="token boolean">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">DEFAULT</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">now</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- HNSW index for approximate nearest neighbor search</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- m=24 and ef_construction=200 are good defaults for 1M+ vectors</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">INDEX</span><span class="token plain"> idx_embeddings_hnsw </span><span class="token keyword" style="color:rgb(86, 156, 214)">ON</span><span class="token plain"> embeddings</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">USING</span><span class="token plain"> hnsw </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">embedding vector_cosine_ops</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">WITH</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">m </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">24</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> ef_construction </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">200</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Metadata index for filtered queries</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">INDEX</span><span class="token plain"> idx_embeddings_metadata </span><span class="token keyword" style="color:rgb(86, 156, 214)">ON</span><span class="token plain"> embeddings </span><span class="token keyword" style="color:rgb(86, 156, 214)">USING</span><span class="token plain"> gin </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">metadata</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="kafka-topic-for-document-ingestion">Kafka Topic for Document Ingestion<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#kafka-topic-for-document-ingestion" class="hash-link" aria-label="Direct link to Kafka Topic for Document Ingestion" title="Direct link to Kafka Topic for Document Ingestion">​</a></h2>
<p>Create a topic for incoming documents. Using multiple partitions allows parallel processing by embedding workers.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Get Kafka connection details</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services get rag-ingest </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--format</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> jq </span><span class="token string" style="color:rgb(206, 145, 120)">'.connection_info'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Create the documents topic with 6 partitions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb kafka topics create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--service</span><span class="token plain"> rag-ingest </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> documents </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--partitions</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">6</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --replication-factor </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--config</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(156, 220, 254)">retention.ms</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style="color:rgb(181, 206, 168)">604800000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Here is a Python consumer that reads documents from Kafka, generates embeddings, and stores them in PostgreSQL:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> kafka </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> KafkaConsumer</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> openai </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> OpenAI</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> psycopg</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Initialize clients</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">openai_client </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> OpenAI</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">pg_conn </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> psycopg</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">connect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql://user:pass@rag-vectors.foundrydb.com/defaultdb?sslmode=verify-full"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">consumer </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> KafkaConsumer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"documents"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    bootstrap_servers</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"rag-ingest.foundrydb.com:9093"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    security_protocol</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"SASL_PLAINTEXT"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    sasl_mechanism</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"SCRAM-SHA-256"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    sasl_plain_username</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"app_user"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    sasl_plain_password</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"your-password"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    value_deserializer</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token keyword" style="color:rgb(86, 156, 214)">lambda</span><span class="token plain"> m</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">m</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">decode</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">"utf-8"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    group_id</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"embedding-workers"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">chunk_text</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">str</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> max_tokens</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">int</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">512</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">-</span><span class="token operator" style="color:rgb(212, 212, 212)">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">list</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token builtin" style="color:rgb(86, 156, 214)">str</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">"""Split text into overlapping chunks."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    words </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">split</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    chunks </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">for</span><span class="token plain"> i </span><span class="token keyword" style="color:rgb(86, 156, 214)">in</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">range</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token number" style="color:rgb(181, 206, 168)">0</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">len</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">words</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> max_tokens </span><span class="token operator" style="color:rgb(212, 212, 212)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        chunk </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">" "</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">words</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain">i </span><span class="token operator" style="color:rgb(212, 212, 212)">+</span><span class="token plain"> max_tokens</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token keyword" style="color:rgb(86, 156, 214)">if</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">            chunks</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">append</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">return</span><span class="token plain"> chunks</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">for</span><span class="token plain"> message </span><span class="token keyword" style="color:rgb(86, 156, 214)">in</span><span class="token plain"> consumer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    doc </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">value</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    chunks </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> chunk_text</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">doc</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"content"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># Batch embed all chunks</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    response </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> openai_client</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embeddings</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">create</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        model</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"text-embedding-3-small"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token builtin" style="color:rgb(86, 156, 214)">input</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">chunks</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># Bulk insert into PostgreSQL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">with</span><span class="token plain"> pg_conn</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">cursor</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">as</span><span class="token plain"> cur</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token keyword" style="color:rgb(86, 156, 214)">for</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> emb_data </span><span class="token keyword" style="color:rgb(86, 156, 214)">in</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">zip</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">chunks</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">            cur</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">execute</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                </span><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">"""INSERT INTO embeddings (content, metadata, embedding)</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">                   VALUES (%s, %s, %s::vector)"""</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">dumps</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">doc</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">"metadata"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> emb_data</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embedding</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    pg_conn</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">commit</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="querying-with-caching">Querying with Caching<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#querying-with-caching" class="hash-link" aria-label="Direct link to Querying with Caching" title="Direct link to Querying with Caching">​</a></h2>
<p>The query path embeds the user's question, searches PostgreSQL for similar vectors, and caches the result in Valkey. Subsequent identical queries return instantly from cache.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> hashlib</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> valkey</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> psycopg</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> openai </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> OpenAI</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">openai_client </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> OpenAI</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">pg_conn </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> psycopg</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">connect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">"postgresql://user:pass@rag-vectors.foundrydb.com/defaultdb?sslmode=verify-full"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">cache </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> valkey</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">Valkey</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    host</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"rag-cache.foundrydb.com"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> port</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style="color:rgb(181, 206, 168)">6380</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    username</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"app_user"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> password</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"your-password"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> ssl</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token boolean">True</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">search</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">str</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> top_k</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">int</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">5</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> cache_ttl</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">int</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">3600</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">-</span><span class="token operator" style="color:rgb(212, 212, 212)">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">list</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token builtin" style="color:rgb(86, 156, 214)">dict</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># Check cache first</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    cache_key </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">f"rag:</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string-interpolation interpolation">hashlib</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token string-interpolation interpolation">sha256</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string-interpolation interpolation">query</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token string-interpolation interpolation">encode</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token string-interpolation interpolation">hexdigest</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    cached </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> cache</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">cache_key</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">if</span><span class="token plain"> cached</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token keyword" style="color:rgb(86, 156, 214)">return</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">cached</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># Embed the query</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    response </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> openai_client</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embeddings</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">create</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        model</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"text-embedding-3-small"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token builtin" style="color:rgb(86, 156, 214)">input</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    query_vec </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token number" style="color:rgb(181, 206, 168)">0</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embedding</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># Similarity search via pgvector</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">with</span><span class="token plain"> pg_conn</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">cursor</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">as</span><span class="token plain"> cur</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        cur</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">execute</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">            </span><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">"""SELECT content, metadata,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">                      1 - (embedding &lt;=&gt; %s::vector) AS similarity</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">               FROM embeddings</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">               ORDER BY embedding &lt;=&gt; %s::vector</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">               LIMIT %s"""</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">query_vec</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> query_vec</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> top_k</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        results </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string" style="color:rgb(206, 145, 120)">"content"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> row</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token number" style="color:rgb(181, 206, 168)">0</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"metadata"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> row</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"similarity"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(86, 156, 214)">float</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">row</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token number" style="color:rgb(181, 206, 168)">2</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">            </span><span class="token keyword" style="color:rgb(86, 156, 214)">for</span><span class="token plain"> row </span><span class="token keyword" style="color:rgb(86, 156, 214)">in</span><span class="token plain"> cur</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">fetchall</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># Cache results</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    cache</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token builtin" style="color:rgb(86, 156, 214)">set</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">cache_key</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">dumps</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">results</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> ex</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">cache_ttl</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">return</span><span class="token plain"> results</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="performance-ivfflat-vs-hnsw">Performance: IVFFlat vs HNSW<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#performance-ivfflat-vs-hnsw" class="hash-link" aria-label="Direct link to Performance: IVFFlat vs HNSW" title="Direct link to Performance: IVFFlat vs HNSW">​</a></h2>
<p>pgvector supports two index types. Choosing the right one depends on your dataset size and query pattern.</p>
<table><thead><tr><th>Index</th><th>Build Time</th><th>Query Speed</th><th>Recall</th><th>Best For</th></tr></thead><tbody><tr><td><strong>HNSW</strong></td><td>Slower (hours at 10M+)</td><td>~1ms</td><td>99%+</td><td>Production queries, high recall requirements</td></tr><tr><td><strong>IVFFlat</strong></td><td>Fast (minutes at 10M+)</td><td>~2-5ms</td><td>95-98%</td><td>Large datasets with acceptable recall tradeoff</td></tr></tbody></table>
<p>For most RAG applications, <strong>HNSW is the right choice</strong>. The recall difference matters: at 95% recall, 1 in 20 queries misses a relevant chunk. At 99%+, missed context is rare.</p>
<p>Two tuning parameters to know:</p>
<ul>
<li><strong><code>ef_search</code></strong> (HNSW): higher values increase recall at the cost of latency. Default is 40; set to 100-200 for production RAG.</li>
<li><strong>Parallel query</strong>: enable <code>SET max_parallel_workers_per_gather = 4</code> for similarity searches across large tables.</li>
</ul>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Tune HNSW search quality (set per session or in postgresql.conf)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SET</span><span class="token plain"> hnsw</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">ef_search </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">150</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Enable parallel workers for large scans</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SET</span><span class="token plain"> max_parallel_workers_per_gather </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">4</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="why-this-stack-works">Why This Stack Works<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#why-this-stack-works" class="hash-link" aria-label="Direct link to Why This Stack Works" title="Direct link to Why This Stack Works">​</a></h2>
<p>This architecture handles the full RAG lifecycle without duct tape:</p>
<ul>
<li><strong>Kafka</strong> decouples document ingestion from embedding generation. You can scale embedding workers independently, replay failed batches, and add new document sources without changing downstream code.</li>
<li><strong>PostgreSQL pgvector</strong> stores vectors alongside your relational data. No need for a separate vector database. You can join embeddings with user tables, filter by metadata using standard SQL, and use transactions for consistency.</li>
<li><strong>Valkey</strong> eliminates redundant embedding API calls and database queries. A 1-hour TTL on cached results cuts costs significantly for repeated queries.</li>
<li><strong>FoundryDB</strong> handles the operational overhead: automated backups, TLS everywhere, monitoring, and all three services in one dashboard.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps">​</a></h2>
<p>Deploy this pipeline on FoundryDB and start indexing your documents. The <a href="https://docs.foundrydb.com/getting-started/quick-start">quick start guide</a> covers creating your first service, and the <a href="https://docs.foundrydb.com/databases/postgresql">PostgreSQL documentation</a> has details on pgvector configuration and tuning.</p>
<p>For production deployments, consider adding read replicas to your PostgreSQL service for query scaling, and enabling Kafka's multi-node mode for ingestion high availability.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="rag" term="rag"/>
        <category label="postgresql" term="postgresql"/>
        <category label="pgvector" term="pgvector"/>
        <category label="kafka" term="kafka"/>
        <category label="valkey" term="valkey"/>
        <category label="ai" term="ai"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Connection Pooling on FoundryDB: PgBouncer and ProxySQL Deep Dive]]></title>
        <id>https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql</id>
        <link href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How to configure and tune connection pooling for PostgreSQL (PgBouncer) and MySQL (ProxySQL) on FoundryDB. Reduce connection overhead, improve throughput, and handle thousands of concurrent connections.]]></summary>
        <content type="html"><![CDATA[<p>Every database connection costs memory. PostgreSQL forks a backend process per connection (roughly 5-10 MB each), and MySQL allocates per-thread buffers that scale with your buffer configuration. At 200 concurrent connections, the overhead is manageable. At 2,000, you are spending gigabytes of RAM on connection state instead of query execution.</p>
<p>Connection pooling sits between your application and the database, multiplexing many client connections over a small number of backend connections. FoundryDB provides PgBouncer for PostgreSQL and ProxySQL for MySQL, both managed through the API with no manual SSH or config file editing required.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-connection-pooling-matters">Why Connection Pooling Matters<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#why-connection-pooling-matters" class="hash-link" aria-label="Direct link to Why Connection Pooling Matters" title="Direct link to Why Connection Pooling Matters">​</a></h2>
<p>Without a pooler, every application process (every serverless function invocation, every container replica, every worker thread) opens its own connection to the database. This creates two problems:</p>
<ul>
<li><strong>Connection overhead.</strong> Each backend connection consumes memory and CPU regardless of whether it is actively running a query. At scale, you hit <code>max_connections</code> limits before you hit actual query throughput limits.</li>
<li><strong>Connection storms.</strong> When an application scales horizontally (auto-scaling containers, Lambda cold starts), dozens of connections open simultaneously. The database spends more time authenticating and forking processes than answering queries.</li>
</ul>
<p>A pooler solves both by maintaining a fixed pool of backend connections and assigning them to client requests on demand. Your application can open 5,000 client connections while the database sees only 50 active backends.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="pgbouncer-for-postgresql">PgBouncer for PostgreSQL<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#pgbouncer-for-postgresql" class="hash-link" aria-label="Direct link to PgBouncer for PostgreSQL" title="Direct link to PgBouncer for PostgreSQL">​</a></h2>
<p>PgBouncer runs on every node of your PostgreSQL service, listening on port <code>6432</code>. Enable it with a single API call.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="enabling-pgbouncer">Enabling PgBouncer<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#enabling-pgbouncer" class="hash-link" aria-label="Direct link to Enabling PgBouncer" title="Direct link to Enabling PgBouncer">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/pooler/enable </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_name": "defaultdb",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_user": "app_user",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "pool_mode": "transaction",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "default_pool_size": 25,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "max_client_conn": 2000</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>database_user</code> must be an existing application user (create one via the <a href="https://docs.foundrydb.com/docs/api">Users API</a> first). Superuser accounts like <code>postgres</code> and internal system users are blocked for security.</p>
<p>The response returns a list of <code>task_ids</code>, one per node. PgBouncer is ready once all tasks reach <code>completed</code> status.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="pool-modes">Pool Modes<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#pool-modes" class="hash-link" aria-label="Direct link to Pool Modes" title="Direct link to Pool Modes">​</a></h3>
<p>The <code>pool_mode</code> parameter controls when a backend connection is returned to the pool.</p>
<table><thead><tr><th>Mode</th><th>Backend returned after</th><th>Best for</th><th>Caveats</th></tr></thead><tbody><tr><td><code>transaction</code></td><td>Each transaction commits/rolls back</td><td>Web apps, APIs, microservices</td><td>Cannot use <code>SET</code>, <code>LISTEN/NOTIFY</code>, or session-level advisory locks</td></tr><tr><td><code>session</code></td><td>Client disconnects</td><td>Apps that rely on session state, prepared statements, temp tables</td><td>Lower multiplexing ratio, needs more backend connections</td></tr><tr><td><code>statement</code></td><td>Each statement completes</td><td>Simple read-only workloads</td><td>Incompatible with multi-statement transactions</td></tr></tbody></table>
<p><strong>Start with <code>transaction</code> mode.</strong> It provides the best multiplexing ratio for most web applications. Switch to <code>session</code> only if your application explicitly uses session-scoped features like <code>SET search_path</code>, advisory locks, or temporary tables.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="tuning-pool-size">Tuning Pool Size<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#tuning-pool-size" class="hash-link" aria-label="Direct link to Tuning Pool Size" title="Direct link to Tuning Pool Size">​</a></h3>
<p>The <code>default_pool_size</code> sets how many backend connections PgBouncer keeps open per (user, database) pair. The right value depends on your workload.</p>
<p><strong>Too small:</strong> Clients queue waiting for a backend connection. You will see <code>max_wait_ms</code> climb in the stats output and query latency increase.</p>
<p><strong>Too large:</strong> You lose the benefit of pooling. The database handles nearly as many connections as it would without a pooler.</p>
<p>A good starting point: set <code>default_pool_size</code> to your PostgreSQL <code>max_connections</code> divided by the number of (user, database) pairs you are pooling, leaving 10-20% headroom for direct admin connections.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Update pool size and timeouts without restarting PgBouncer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PATCH </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/pooler/config </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "default_pool_size": 40,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "server_idle_timeout_seconds": 600,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "query_wait_timeout_seconds": 120</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>After updating, reload PgBouncer to apply the changes to all nodes without dropping active connections:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/pooler/reload</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="proxysql-for-mysql">ProxySQL for MySQL<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#proxysql-for-mysql" class="hash-link" aria-label="Direct link to ProxySQL for MySQL" title="Direct link to ProxySQL for MySQL">​</a></h2>
<p>ProxySQL serves the same purpose for MySQL, listening on port <code>6033</code> by default. It adds connection multiplexing and built-in health monitoring.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="enabling-proxysql">Enabling ProxySQL<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#enabling-proxysql" class="hash-link" aria-label="Direct link to Enabling ProxySQL" title="Direct link to Enabling ProxySQL">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/proxysql/enable </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_user": "app_user",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "listen_port": 6033,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "max_connections": 500</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Like PgBouncer, the <code>database_user</code> must be an existing application user. System accounts (<code>root</code>, <code>admin</code>, <code>mdb_replication</code>, <code>proxysql_monitor</code>, and others) are blocked.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="tuning-proxysql">Tuning ProxySQL<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#tuning-proxysql" class="hash-link" aria-label="Direct link to Tuning ProxySQL" title="Direct link to Tuning ProxySQL">​</a></h3>
<p>ProxySQL exposes a rich configuration surface. The most common tuning parameters:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PATCH </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/proxysql/config </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "max_connections": 1000,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "default_max_connections": 200,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "default_query_timeout_ms": 30000,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "connect_timeout_ms": 5000,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "multiplexing_enabled": true</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<table><thead><tr><th>Parameter</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><code>max_connections</code></td><td>200</td><td>Total maximum backend connections across all servers</td></tr><tr><td><code>default_max_connections</code></td><td>200</td><td>Max connections per backend server</td></tr><tr><td><code>default_query_timeout_ms</code></td><td>0 (disabled)</td><td>Kill queries exceeding this threshold (max 86400000)</td></tr><tr><td><code>connect_timeout_ms</code></td><td>1000</td><td>Timeout for establishing backend connections (100-60000)</td></tr><tr><td><code>multiplexing_enabled</code></td><td>true</td><td>Reuse backend connections across client sessions</td></tr><tr><td><code>monitor_enabled</code></td><td>true</td><td>ProxySQL health checks on backend servers</td></tr><tr><td><code>ping_interval_ms</code></td><td>10000</td><td>How often to ping backends for health checks</td></tr></tbody></table>
<p>After changes, reload ProxySQL to apply them at runtime:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/proxysql/reload</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="monitoring-pool-statistics">Monitoring Pool Statistics<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#monitoring-pool-statistics" class="hash-link" aria-label="Direct link to Monitoring Pool Statistics" title="Direct link to Monitoring Pool Statistics">​</a></h2>
<p>Both poolers expose real-time statistics through the API.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="pgbouncer-stats">PgBouncer Stats<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#pgbouncer-stats" class="hash-link" aria-label="Direct link to PgBouncer Stats" title="Direct link to PgBouncer Stats">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Request stats collection (returns task_ids for polling)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/pooler/stats</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response includes per-node metrics: <code>active_clients</code>, <code>waiting_clients</code>, <code>active_servers</code>, <code>idle_servers</code>, <code>max_wait_ms</code>, and <code>avg_query_time_us</code>. Watch <code>waiting_clients</code> and <code>max_wait_ms</code> closely. If clients are consistently waiting, increase <code>default_pool_size</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="proxysql-stats">ProxySQL Stats<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#proxysql-stats" class="hash-link" aria-label="Direct link to ProxySQL Stats" title="Direct link to ProxySQL Stats">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">serviceId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/proxysql/stats</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>ProxySQL stats include <code>total_connections</code>, <code>active_connections</code>, <code>idle_connections</code>, <code>connection_errors</code>, and per-server breakdowns with <code>connections_used</code>, <code>connections_free</code>, and query counts.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="when-to-use-pooling-vs-direct-connections">When to Use Pooling vs. Direct Connections<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#when-to-use-pooling-vs-direct-connections" class="hash-link" aria-label="Direct link to When to Use Pooling vs. Direct Connections" title="Direct link to When to Use Pooling vs. Direct Connections">​</a></h2>
<p>Connection pooling is not always the right answer. Here is a quick decision guide.</p>
<p><strong>Use a pooler when:</strong></p>
<ul>
<li>Your application opens more than 100 concurrent connections</li>
<li>You run serverless functions or auto-scaling containers that create short-lived connections</li>
<li>You want to protect the database from connection storms during deployment rollouts</li>
<li>Your application framework does not include built-in connection pooling</li>
</ul>
<p><strong>Skip the pooler when:</strong></p>
<ul>
<li>You have fewer than 50 total connections and they are long-lived</li>
<li>Your application relies heavily on session-level features (prepared statements, temp tables, <code>LISTEN/NOTIFY</code>) and cannot use transaction mode</li>
<li>You are running batch jobs that hold connections for minutes at a time, where pooling provides no benefit</li>
</ul>
<p><strong>Application-level poolers vs. FoundryDB poolers:</strong> If your framework already provides connection pooling (like HikariCP for Java or pgx pool for Go), you can still benefit from a server-side pooler. The application pool handles connection lifecycle in your process, while PgBouncer/ProxySQL handles multiplexing at the database level. They complement each other, especially in multi-service architectures where several applications share one database.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-next">What's Next<a href="https://docs.foundrydb.com/blog/connection-pooling-pgbouncer-proxysql#whats-next" class="hash-link" aria-label="Direct link to What's Next" title="Direct link to What's Next">​</a></h2>
<ul>
<li><a href="https://docs.foundrydb.com/docs/databases/postgresql">PostgreSQL documentation</a> for connection strings and TLS configuration</li>
<li><a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide">Read replicas guide</a> to combine pooling with horizontal read scaling</li>
<li><a href="https://docs.foundrydb.com/" target="_blank" rel="noopener noreferrer">Connection pooling API reference</a> for the full list of configuration parameters</li>
</ul>
<p>Connection pooling is one of the highest-impact optimizations you can make with minimal application changes. On FoundryDB, it takes one API call to enable and a few parameters to tune. Start with <code>transaction</code> mode for PostgreSQL or <code>multiplexing_enabled: true</code> for MySQL, monitor the stats for a week, and adjust from there.</p>
<p><a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">Create a free FoundryDB service</a> and enable connection pooling in under five minutes.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="postgresql" term="postgresql"/>
        <category label="mysql" term="mysql"/>
        <category label="pgbouncer" term="pgbouncer"/>
        <category label="proxysql" term="proxysql"/>
        <category label="connection-pooling" term="connection-pooling"/>
        <category label="performance" term="performance"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[From 5 Database Providers to 1: Why We Built a Multi-Engine Platform]]></title>
        <id>https://docs.foundrydb.com/blog/from-5-database-providers-to-1</id>
        <link href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Managing databases across multiple providers creates operational overhead. FoundryDB consolidates 5 engines into one platform with unified tooling.]]></summary>
        <content type="html"><![CDATA[<p>If you run a modern application stack, you probably use at least three different database engines. PostgreSQL for your application data. MongoDB or another document store for unstructured content. Valkey (or Redis) for caching and session storage. Kafka for event streaming. Maybe MySQL for a legacy service that nobody wants to migrate.</p>
<p>Each engine runs on a different managed provider. Each provider has its own dashboard, its own CLI, its own billing, its own alerting system, its own way of handling backups, its own access control model. You pay five bills, manage five sets of credentials, and context-switch between five different interfaces when something goes wrong at 2 AM.</p>
<p>We built FoundryDB to solve this problem: one platform for all your database engines, with a single API, a single dashboard, and a single bill.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-real-cost-of-multi-provider-sprawl">The Real Cost of Multi-Provider Sprawl<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#the-real-cost-of-multi-provider-sprawl" class="hash-link" aria-label="Direct link to The Real Cost of Multi-Provider Sprawl" title="Direct link to The Real Cost of Multi-Provider Sprawl">​</a></h2>
<p>The sticker price of a managed database is the easy part. The hidden costs are operational.</p>
<p><strong>Context switching.</strong> Your on-call engineer gets paged about a slow query on PostgreSQL. They log into Provider A. Then they get an alert about a Kafka consumer lag spike. That is Provider D, different credentials, different dashboard, different mental model for what the metrics mean. Every provider switch costs 5-15 minutes of reorientation.</p>
<p><strong>Inconsistent tooling.</strong> Provider A uses Terraform for infrastructure-as-code. Provider B has a CLI that works differently. Provider C has a REST API with different authentication. Your automation scripts are a patchwork of provider-specific integrations, each with its own failure modes.</p>
<p><strong>Billing complexity.</strong> Five invoices, five pricing models, five ways of calculating storage and compute. Some charge per hour, some per minute, some per GB-month. Forecasting database costs across providers requires a spreadsheet that nobody maintains accurately.</p>
<p><strong>Alerting gaps.</strong> Each provider has its own monitoring. Your PostgreSQL provider sends alerts to PagerDuty. Your Kafka provider sends to Opsgenie. Your Redis provider emails someone who left the company six months ago. Unified observability requires stitching together multiple metric sources, and the seams always show.</p>
<p><strong>Access control fragmentation.</strong> Five providers means five IAM systems. Onboarding a new engineer requires creating accounts on five platforms. Offboarding requires revoking access across five platforms. Audit trails live in five different places.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="one-platform-five-engines">One Platform, Five Engines<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#one-platform-five-engines" class="hash-link" aria-label="Direct link to One Platform, Five Engines" title="Direct link to One Platform, Five Engines">​</a></h2>
<p>FoundryDB supports PostgreSQL, MySQL, MongoDB, Valkey, and Kafka. Every engine gets the same operational treatment: same API, same CLI, same dashboard, same monitoring, same backup system, same HA model.</p>
<p>Here is what that looks like in practice.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="single-cli-for-everything">Single CLI for Everything<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#single-cli-for-everything" class="hash-link" aria-label="Direct link to Single CLI for Everything" title="Direct link to Single CLI for Everything">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Create a PostgreSQL service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> app-db </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> postgresql </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">17</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-4 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">100</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Create a MongoDB service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> content-store </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> mongodb </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">7</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-3 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">50</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Create a Valkey cache</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> session-cache </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> valkey </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">8.1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-2 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">20</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Create a Kafka cluster</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> events </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> kafka </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">3.9</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-4 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">200</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># List all services, regardless of engine</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services list</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Same command structure, same flags, same output format. The <code>--engine</code> flag is the only difference.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="unified-dashboard">Unified Dashboard<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#unified-dashboard" class="hash-link" aria-label="Direct link to Unified Dashboard" title="Direct link to Unified Dashboard">​</a></h3>
<p>One login. One view of all your services across all engines. CPU usage, memory, connections, storage, replication lag, backup status. All in the same place, with the same visual language.</p>
<p>No more bookmarking five different provider dashboards. No more remembering which provider uses "instances" vs "clusters" vs "deployments."</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="one-api">One API<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#one-api" class="hash-link" aria-label="Direct link to One API" title="Direct link to One API">​</a></h3>
<p>Every operation goes through the same REST API:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># All these use the same base URL, same auth, same response format</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services              </span><span class="token comment" style="color:rgb(106, 153, 85)"># List all</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services/</span><span class="token variable" style="color:rgb(156, 220, 254)">$PG_ID</span><span class="token plain">       </span><span class="token comment" style="color:rgb(106, 153, 85)"># PostgreSQL details</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services/</span><span class="token variable" style="color:rgb(156, 220, 254)">$MONGO_ID</span><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># MongoDB details</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services/</span><span class="token variable" style="color:rgb(156, 220, 254)">$KAFKA_ID</span><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)"># Kafka details</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Backups: same endpoint pattern for all engines</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services/</span><span class="token variable" style="color:rgb(156, 220, 254)">$PG_ID</span><span class="token plain">/backups</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services/</span><span class="token variable" style="color:rgb(156, 220, 254)">$MONGO_ID</span><span class="token plain">/backups</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Users: same endpoint pattern for all engines</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services/</span><span class="token variable" style="color:rgb(156, 220, 254)">$PG_ID</span><span class="token plain">/users</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token plain"> https://api.foundrydb.com/v1/services/</span><span class="token variable" style="color:rgb(156, 220, 254)">$VALKEY_ID</span><span class="token plain">/users</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Your Terraform modules, CI/CD pipelines, and automation scripts use one provider plugin, one authentication method, one response schema. When you add a new database engine to your stack, your existing tooling already supports it.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="consistent-ha-and-failover">Consistent HA and Failover<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#consistent-ha-and-failover" class="hash-link" aria-label="Direct link to Consistent HA and Failover" title="Direct link to Consistent HA and Failover">​</a></h3>
<p>High availability works the same way across engines. Add read replicas, configure automatic failover, and monitor replication lag using the same API and dashboard regardless of whether it is PostgreSQL streaming replication, MySQL GTID replication, MongoDB replica sets, or Valkey Sentinel.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Add a read replica to PostgreSQL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services add-replica </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--service</span><span class="token plain"> app-db </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Add a read replica to MySQL (same command, same flags)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services add-replica </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--service</span><span class="token plain"> legacy-mysql </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="unified-monitoring-and-alerting">Unified Monitoring and Alerting<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#unified-monitoring-and-alerting" class="hash-link" aria-label="Direct link to Unified Monitoring and Alerting" title="Direct link to Unified Monitoring and Alerting">​</a></h3>
<p>FoundryDB exports metrics to 7 destinations: Prometheus, Datadog, Grafana Cloud, New Relic, Elastic, InfluxDB, and our built-in dashboard. You configure the export once at the organization level, and every service (regardless of engine) sends metrics to the same place.</p>
<p>Alert rules follow the same pattern. A "high CPU" alert on PostgreSQL and a "high CPU" alert on Kafka use the same rule definition, the same notification channels, the same escalation policies.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Create an alert rule that applies to any service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb alerts create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"High CPU"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--metric</span><span class="token plain"> cpu_usage_percent </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--threshold</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">85</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--duration</span><span class="token plain"> 5m </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--notify</span><span class="token plain"> slack:</span><span class="token comment" style="color:rgb(106, 153, 85)">#database-alerts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="multi-engine-stacks">Multi-Engine Stacks<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#multi-engine-stacks" class="hash-link" aria-label="Direct link to Multi-Engine Stacks" title="Direct link to Multi-Engine Stacks">​</a></h2>
<p>Many applications need multiple engines working together. FoundryDB makes it easy to deploy coordinated stacks.</p>
<p><strong>RAG Pipeline</strong>: PostgreSQL (pgvector) + Kafka (ingestion) + Valkey (cache). Deploy all three in one zone, connected over the private network.</p>
<p><strong>E-commerce</strong>: PostgreSQL (orders, inventory) + MongoDB (product catalog) + Valkey (session store, cart cache).</p>
<p><strong>Event-driven microservices</strong>: Kafka (event bus) + PostgreSQL (per-service databases) + Valkey (distributed locks, rate limiting).</p>
<p><strong>Analytics</strong>: PostgreSQL (OLTP source) + Kafka (CDC streaming) + MongoDB (denormalized read models).</p>
<p>Because all services share the same FoundryDB network within a zone, inter-service communication uses private IPs with sub-millisecond latency. No public internet traversal, no additional firewall rules.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-honest-tradeoff">The Honest Tradeoff<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#the-honest-tradeoff" class="hash-link" aria-label="Direct link to The Honest Tradeoff" title="Direct link to The Honest Tradeoff">​</a></h2>
<p>We believe in being transparent about limitations. FoundryDB runs on UpCloud infrastructure. We are not a multi-cloud platform. If your requirement is to run PostgreSQL on AWS in us-east-1 and MongoDB on GCP in europe-west1, FoundryDB is not the right fit.</p>
<p>What we offer instead: a focused, well-integrated platform on high-quality European infrastructure. Every engine gets first-class support because we are not spreading across three cloud providers. Our PostgreSQL on UpCloud MaxIOPS storage competes with (and often beats) equivalent offerings on hyperscaler providers in throughput and latency benchmarks.</p>
<p>If your priority is reducing operational complexity, consolidating billing, and running on EU infrastructure, the single-provider tradeoff is usually worth it. If your priority is multi-cloud or specific cloud-native integrations (Lambda triggers on DynamoDB, BigQuery federated queries), a hyperscaler-native offering is a better fit.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-consolidation-looks-like">What Consolidation Looks Like<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#what-consolidation-looks-like" class="hash-link" aria-label="Direct link to What Consolidation Looks Like" title="Direct link to What Consolidation Looks Like">​</a></h2>
<p>Here is a before-and-after for a typical mid-size SaaS company:</p>
<table><thead><tr><th>Before</th><th>After</th></tr></thead><tbody><tr><td>5 provider dashboards</td><td>1 FoundryDB dashboard</td></tr><tr><td>5 CLI tools</td><td>1 <code>fdb</code> CLI</td></tr><tr><td>5 Terraform providers</td><td>1 Terraform provider</td></tr><tr><td>5 billing invoices</td><td>1 invoice</td></tr><tr><td>5 IAM systems</td><td>1 API key system</td></tr><tr><td>5 monitoring integrations</td><td>1 metric export config</td></tr><tr><td>5 backup policies</td><td>1 unified backup system</td></tr><tr><td>~3 hours/week on provider context-switching</td><td>0</td></tr></tbody></table>
<p>The migration path is straightforward: create services on FoundryDB, migrate data using standard tools (pg_dump/pg_restore, mongodump/mongorestore, Kafka MirrorMaker), switch your connection strings, and decommission the old providers one at a time.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://docs.foundrydb.com/blog/from-5-database-providers-to-1#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<p>Deploy a multi-engine stack on FoundryDB today. The <a href="https://docs.foundrydb.com/getting-started/quick-start">quick start guide</a> walks through creating your first service, and you can have all five engines running within minutes. Each engine page (<a href="https://docs.foundrydb.com/databases/postgresql">PostgreSQL</a>, <a href="https://docs.foundrydb.com/databases/mysql">MySQL</a>, <a href="https://docs.foundrydb.com/databases/mongodb">MongoDB</a>, <a href="https://docs.foundrydb.com/databases/valkey">Valkey</a>, <a href="https://docs.foundrydb.com/databases/kafka">Kafka</a>) covers engine-specific features and configuration.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="platform" term="platform"/>
        <category label="devops" term="devops"/>
        <category label="postgresql" term="postgresql"/>
        <category label="mysql" term="mysql"/>
        <category label="mongodb" term="mongodb"/>
        <category label="valkey" term="valkey"/>
        <category label="kafka" term="kafka"/>
        <category label="multi-engine" term="multi-engine"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Database Forking: Create Production Clones for Testing in Minutes]]></title>
        <id>https://docs.foundrydb.com/blog/database-forking-testing-staging</id>
        <link href="https://docs.foundrydb.com/blog/database-forking-testing-staging"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Fork your production database into an isolated copy for testing, staging, or experimentation. No data export, no downtime, just a single API call.]]></summary>
        <content type="html"><![CDATA[<p>Testing against realistic data is the difference between catching bugs before production and catching them in production. But getting a faithful copy of your production database into a staging environment usually means writing export scripts, waiting for dumps to transfer, provisioning infrastructure, and importing the data. For a 100 GB PostgreSQL database, that process can take hours and requires someone to babysit it.</p>
<p>FoundryDB's fork endpoint eliminates this entire workflow. One API call creates a fully independent copy of your database, running on its own VM with its own credentials, restored from a backup of the source service. The source database is never touched. The fork is provisioned, restored, and ready for connections in minutes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-a-database-fork">What Is a Database Fork?<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#what-is-a-database-fork" class="hash-link" aria-label="Direct link to What Is a Database Fork?" title="Direct link to What Is a Database Fork?">​</a></h2>
<p>A fork creates a new FoundryDB service by restoring from a backup of an existing service. The new service inherits the same database engine, version, compute plan, storage configuration, zone, and allowed CIDRs as the source. Once provisioned, it is completely independent: it has its own VM, its own DNS endpoint, its own credentials, and its own backup schedule.</p>
<p>The fork is not a read replica. There is no replication link to the source. Writes to the fork do not affect the source, and writes to the source do not appear in the fork. This isolation is what makes forks safe for destructive testing.</p>
<p>Forking is supported for PostgreSQL, MySQL, MongoDB, Valkey, and Kafka. All database engines that support backups can be forked.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-fork-instead-of-dump-and-restore">Why Fork Instead of Dump and Restore?<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#why-fork-instead-of-dump-and-restore" class="hash-link" aria-label="Direct link to Why Fork Instead of Dump and Restore?" title="Direct link to Why Fork Instead of Dump and Restore?">​</a></h2>
<p>The traditional approach to creating a test copy of a production database involves <code>pg_dump</code>, <code>mysqldump</code>, or <code>mongodump</code>, a file transfer, and a manual import on the target. This has three problems.</p>
<p><strong>It is slow.</strong> Dumping and restoring a large database can take hours. Forking uses FoundryDB's existing backup infrastructure (pgBackRest for PostgreSQL, native backup tooling for other engines), which is already optimized for speed.</p>
<p><strong>It is manual.</strong> Someone has to run the dump, transfer the file, create the target database, import the data, and verify the result. Forking is one API call.</p>
<p><strong>It touches production.</strong> Running <code>pg_dump</code> on a production database adds load to the primary. Forking restores from an existing backup, so the source database sees zero additional load.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="use-cases">Use Cases<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#use-cases" class="hash-link" aria-label="Direct link to Use Cases" title="Direct link to Use Cases">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="staging-environments">Staging environments<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#staging-environments" class="hash-link" aria-label="Direct link to Staging environments" title="Direct link to Staging environments">​</a></h3>
<p>Fork your production database before each release to validate migrations and application changes against real data. Since forks are cheap and fast, you can create a fresh one for every deploy cycle instead of maintaining a long-lived staging database that drifts out of sync.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="schema-migration-testing">Schema migration testing<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#schema-migration-testing" class="hash-link" aria-label="Direct link to Schema migration testing" title="Direct link to Schema migration testing">​</a></h3>
<p>Run your migration scripts against a fork before applying them to production. If the migration fails or produces unexpected results, delete the fork and iterate. The production database is never at risk.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="load-testing">Load testing<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#load-testing" class="hash-link" aria-label="Direct link to Load testing" title="Direct link to Load testing">​</a></h3>
<p>Fork your database, point your load testing tool at the fork's DNS endpoint, and run your benchmarks against realistic data volumes. When the test finishes, delete the fork.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="feature-branch-databases">Feature branch databases<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#feature-branch-databases" class="hash-link" aria-label="Direct link to Feature branch databases" title="Direct link to Feature branch databases">​</a></h3>
<p>Give each feature branch its own database fork. Developers can test against production-scale data without competing for shared staging resources. Combined with FoundryDB's TTL (auto-deletion) feature, these forks can clean themselves up automatically.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-fork-via-the-api">Creating a Fork via the API<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#creating-a-fork-via-the-api" class="hash-link" aria-label="Direct link to Creating a Fork via the API" title="Direct link to Creating a Fork via the API">​</a></h2>
<p>The fork endpoint is <code>POST /managed-services/{source-service-id}/fork</code>. The source service must be in <code>Running</code> state and must have at least one completed backup.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="fork-from-the-latest-backup">Fork from the latest backup<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#fork-from-the-latest-backup" class="hash-link" aria-label="Direct link to Fork from the latest backup" title="Direct link to Fork from the latest backup">​</a></h3>
<p>If you omit <code>backup_id</code>, FoundryDB uses the most recent completed backup automatically.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">source-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/fork </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"name": "staging-fork"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response is a <code>202 Accepted</code> with the new service object. The <code>status</code> field will show the initial provisioning state. The fork goes through the standard provisioning pipeline (network, server, agent, DNS, restore, health check) and transitions to <code>Running</code> once the backup has been restored and validated.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="fork-from-a-specific-backup">Fork from a specific backup<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#fork-from-a-specific-backup" class="hash-link" aria-label="Direct link to Fork from a specific backup" title="Direct link to Fork from a specific backup">​</a></h3>
<p>If you need to fork from a particular point in time, pass the <code>backup_id</code> explicitly. First, list the available backups for the source service.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># List completed backups for the source service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">source-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> jq </span><span class="token string" style="color:rgb(206, 145, 120)">'.backups[] | select(.status == "Completed") | {id, created_at, type}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"7c9e6679-7425-40de-944b-e07fc1f90ae7"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-04-05T02:00:00Z"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"automated"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"a1b2c3d4-e5f6-7890-abcd-ef1234567890"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-04-04T02:00:00Z"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"automated"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Then create the fork from the specific backup.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">source-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/fork </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "name": "pre-migration-snapshot",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "backup_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="fork-isolation">Fork Isolation<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#fork-isolation" class="hash-link" aria-label="Direct link to Fork Isolation" title="Direct link to Fork Isolation">​</a></h2>
<p>Each fork runs on a completely separate VM. There is no shared infrastructure between the source and the fork.</p>
<table><thead><tr><th>Property</th><th>Source service</th><th>Forked service</th></tr></thead><tbody><tr><td>VM</td><td>Original VM</td><td>New, dedicated VM</td></tr><tr><td>DNS endpoint</td><td>Original domain</td><td>New, unique domain</td></tr><tr><td>Credentials</td><td>Original users/passwords</td><td>New, independent credentials</td></tr><tr><td>Backup schedule</td><td>Existing schedule</td><td>New, independent schedule</td></tr><tr><td>Allowed CIDRs</td><td>Inherited at fork time</td><td>Independently configurable</td></tr><tr><td>Compute plan</td><td>Original plan</td><td>Same plan (independently scalable)</td></tr></tbody></table>
<p>After the fork is created, you can modify it without affecting the source. Scale it up, scale it down, change the allowed CIDRs, create new database users, or drop tables. None of these operations propagate back to the source.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-fork-progress">Monitoring Fork Progress<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#monitoring-fork-progress" class="hash-link" aria-label="Direct link to Monitoring Fork Progress" title="Direct link to Monitoring Fork Progress">​</a></h2>
<p>Forked services go through the same provisioning pipeline as new services. You can monitor progress using the task summary endpoint.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">fork-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/task-summary </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> jq </span><span class="token string" style="color:rgb(206, 145, 120)">'{status, current_task, progress_pct}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 fork transitions through these states: <code>SetupNetwork</code>, <code>SetupServer</code>, <code>SetupAgent</code>, <code>SetupDNS</code>, <code>ProvisioningRestore</code> (where the backup is restored), <code>ProvisioningHealth</code>, and finally <code>Running</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cleanup">Cleanup<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#cleanup" class="hash-link" aria-label="Direct link to Cleanup" title="Direct link to Cleanup">​</a></h2>
<p>Forks are full services with their own compute and storage resources. Remember to delete them when you are done.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> DELETE </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">fork-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>For ephemeral use cases like CI/CD pipelines or feature branch databases, consider setting a TTL when creating your services. FoundryDB supports auto-deletion after a configurable number of hours (1 to 720), so your test forks clean themselves up without manual intervention.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cicd-integration">CI/CD Integration<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#cicd-integration" class="hash-link" aria-label="Direct link to CI/CD Integration" title="Direct link to CI/CD Integration">​</a></h2>
<p>Database forks fit naturally into CI/CD pipelines. Here is a pattern for GitHub Actions that creates a fork before running migration tests and tears it down afterward.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token key atrule">migration-test</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain"> </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> actions/checkout@v4</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> Fork production database</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> fork</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">|</span><span class="token scalar string" style="color:rgb(206, 145, 120)"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">          RESPONSE=$(curl -s -u ${{ secrets.FDB_API_KEY }}:${{ secrets.FDB_API_SECRET }} \</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">            -X POST https://api.foundrydb.com/managed-services/${{ vars.PROD_SERVICE_ID }}/fork \</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">            -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">            -d '{"name": "ci-migration-${{ github.run_id }}"}')</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">          echo "fork_id=$(echo $RESPONSE | jq -r '.id')" &gt;&gt; $GITHUB_OUTPUT</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> Wait for fork to be ready</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">|</span><span class="token scalar string" style="color:rgb(206, 145, 120)"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">          for i in $(seq 1 60); do</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">            STATUS=$(curl -s -u ${{ secrets.FDB_API_KEY }}:${{ secrets.FDB_API_SECRET }} \</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">              https://api.foundrydb.com/managed-services/${{ steps.fork.outputs.fork_id }} \</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">              | jq -r '.status')</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">            if [ "$STATUS" = "Running" ]; then break; fi</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">            sleep 10</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">          done</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> Run migrations against fork</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> ./run</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">migrations.sh </span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain">target $</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> steps.fork.outputs.fork_id </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(212, 212, 212)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> Delete fork</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token key atrule">if</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> always()</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">|</span><span class="token scalar string" style="color:rgb(206, 145, 120)"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">          curl -s -u ${{ secrets.FDB_API_KEY }}:${{ secrets.FDB_API_SECRET }} \</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token scalar string" style="color:rgb(206, 145, 120)">            -X DELETE https://api.foundrydb.com/managed-services/${{ steps.fork.outputs.fork_id }}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This pattern ensures every pull request validates migrations against a fresh copy of production data, and the fork is always cleaned up, even if the migration step fails.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-next">What's Next<a href="https://docs.foundrydb.com/blog/database-forking-testing-staging#whats-next" class="hash-link" aria-label="Direct link to What's Next" title="Direct link to What's Next">​</a></h2>
<p>Database forking is available today for PostgreSQL, MySQL, MongoDB, and Valkey services on FoundryDB. To get started:</p>
<ul>
<li><a href="https://docs.foundrydb.com/getting-started/" target="_blank" rel="noopener noreferrer">Create your first service</a> and trigger a backup</li>
<li>Fork it using the API examples above</li>
<li>Read the <a href="https://docs.foundrydb.com/blog/automated-backups-pitr-guide">backup and PITR guide</a> to understand the backup infrastructure that powers forks</li>
<li>Explore the <a href="https://docs.foundrydb.com/api/" target="_blank" rel="noopener noreferrer">API reference</a> for the full fork endpoint specification</li>
</ul>
<p>If you are not yet on FoundryDB, <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">sign up</a> and have your first database running in under five minutes.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="forking" term="forking"/>
        <category label="testing" term="testing"/>
        <category label="staging" term="staging"/>
        <category label="clone" term="clone"/>
        <category label="development" term="development"/>
        <category label="ci-cd" term="ci-cd"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Automatic Embedding Generation: Build RAG Without the Plumbing]]></title>
        <id>https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag</id>
        <link href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[FoundryDB's managed embedding pipelines auto-vectorize your PostgreSQL data using OpenAI or Cohere models. No ETL scripts, no cron jobs, just configure and query.]]></summary>
        <content type="html"><![CDATA[<p>Every RAG system needs the same boring middle layer: watch a table for changes, call an embedding API, write vectors back, handle retries, manage batches, build indexes, schedule cron jobs, and pray nothing drifts out of sync at 3 AM. FoundryDB's managed embedding pipelines eliminate that entire layer. You configure a pipeline, and your PostgreSQL data gets auto-vectorized with an HNSW index, ready for similarity search.</p>
<p>No ETL scripts. No cron jobs. No model orchestration code.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem-with-diy-embedding-pipelines">The Problem with DIY Embedding Pipelines<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#the-problem-with-diy-embedding-pipelines" class="hash-link" aria-label="Direct link to The Problem with DIY Embedding Pipelines" title="Direct link to The Problem with DIY Embedding Pipelines">​</a></h2>
<p>If you have built a RAG application, you have written some version of this pipeline:</p>
<ol>
<li>A script queries your source table for new or changed rows.</li>
<li>It concatenates text columns, calls OpenAI or Cohere, and receives vectors.</li>
<li>It writes those vectors to a separate table (or the same table, if you enjoy schema headaches).</li>
<li>A cron job or queue worker runs this every few minutes.</li>
<li>You add retry logic for API rate limits and transient failures.</li>
<li>You create and maintain a pgvector HNSW index.</li>
<li>You monitor for drift: rows that were inserted but never embedded, embeddings from deleted rows, schema changes that silently break the pipeline.</li>
</ol>
<p>This works. It also means you are maintaining a custom data pipeline for every table you want to embed. Each one needs monitoring, error handling, and operational attention. For a team that just wants to ship a search feature or a chatbot, this is overhead that adds no user value.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-managed-embedding-pipelines-work">How Managed Embedding Pipelines Work<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#how-managed-embedding-pipelines-work" class="hash-link" aria-label="Direct link to How Managed Embedding Pipelines Work" title="Direct link to How Managed Embedding Pipelines Work">​</a></h2>
<p>FoundryDB handles the entire flow on the database VM itself. When you create a pipeline via the API, the system:</p>
<ol>
<li>Verifies that pgvector is installed on your PostgreSQL service.</li>
<li>Discovers the primary key of your source table.</li>
<li>Creates a companion table (e.g., <code>articles_embeddings</code>) with a <code>vector</code> column sized to your model's dimensions.</li>
<li>Builds an HNSW index on that column using cosine distance (<code>vector_cosine_ops</code>) with <code>m = 16</code> and <code>ef_construction = 64</code>.</li>
<li>Starts a background worker on the primary node that polls the source table at a configurable interval.</li>
<li>On each poll, the worker detects new or changed rows using text hashes, batches them, calls the embedding provider, and writes the results to the companion table.</li>
</ol>
<p>The pipeline transitions through well-defined states: <code>pending</code>, <code>configuring</code>, <code>active</code>, <code>paused</code>, <code>failed</code>, and <code>deleting</code>. You can pause a pipeline without losing state, resume it to process rows that accumulated while paused, or delete it and optionally drop the companion table.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-pipeline">Creating a Pipeline<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#creating-a-pipeline" class="hash-link" aria-label="Direct link to Creating a Pipeline" title="Direct link to Creating a Pipeline">​</a></h2>
<p>Prerequisites: a PostgreSQL service in <code>Running</code> state with the pgvector extension installed. The easiest way is to include <code>"extensions": ["vector"]</code> at service creation time, or use the <code>agent-postgresql-rag</code> preset which includes pgvector automatically.</p>
<p>Once your service is running, create a pipeline with a single API call:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:pass </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">service-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/embedding-pipelines </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "source_table": "articles",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "text_columns": ["title", "body"],</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "model_provider": "openai",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "embedding_model": "text-embedding-3-small",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "model_dimensions": 1536,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "provider_api_key": "sk-...",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_name": "defaultdb",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "batch_size": 100,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "poll_interval_seconds": 30</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>That is the entire setup. FoundryDB creates the companion table <code>articles_embeddings</code>, builds the HNSW index, and starts processing rows. The <code>provider_api_key</code> is encrypted at rest in the controller database and only transmitted to the agent when it needs to call the embedding API.</p>
<p>The response includes the pipeline ID and status. Within seconds, the status transitions from <code>pending</code> to <code>configuring</code> to <code>active</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="supported-model-providers">Supported Model Providers<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#supported-model-providers" class="hash-link" aria-label="Direct link to Supported Model Providers" title="Direct link to Supported Model Providers">​</a></h2>
<p>FoundryDB supports three provider types:</p>
<table><thead><tr><th>Provider</th><th>Example Models</th><th>Default Dimensions</th></tr></thead><tbody><tr><td><strong>OpenAI</strong></td><td><code>text-embedding-3-small</code>, <code>text-embedding-3-large</code></td><td>1536 / 3072</td></tr><tr><td><strong>Cohere</strong></td><td><code>embed-english-v3.0</code></td><td>1024</td></tr><tr><td><strong>Custom</strong></td><td>Any OpenAI-compatible endpoint</td><td>Configurable (1 to 8192)</td></tr></tbody></table>
<p>The <code>custom</code> provider accepts a <code>provider_base_url</code> field pointing to any endpoint that implements the OpenAI <code>/v1/embeddings</code> format. This works with self-hosted models, Azure OpenAI, or any compatible proxy.</p>
<p>For models that support variable dimensions (such as <code>text-embedding-3-small</code>), you can override the default by setting <code>model_dimensions</code> to a lower value like 512. Smaller vectors reduce storage and improve query speed at a modest accuracy tradeoff.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="querying-your-embeddings">Querying Your Embeddings<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#querying-your-embeddings" class="hash-link" aria-label="Direct link to Querying Your Embeddings" title="Direct link to Querying Your Embeddings">​</a></h2>
<p>Once the pipeline is active and rows have been processed, query the companion table using standard pgvector operators. The HNSW index makes approximate nearest-neighbor search fast without any additional configuration.</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Find the 5 most similar articles to a query embedding</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">title</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embedding </span><span class="token operator" style="color:rgb(212, 212, 212)">&lt;=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'[0.1, 0.2, ...]'</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">AS</span><span class="token plain"> distance</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> articles a</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">JOIN</span><span class="token plain"> articles_embeddings e </span><span class="token keyword" style="color:rgb(86, 156, 214)">ON</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">source_row_id::</span><span class="token keyword" style="color:rgb(86, 156, 214)">int</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">id</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embedding </span><span class="token operator" style="color:rgb(212, 212, 212)">&lt;=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'[0.1, 0.2, ...]'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">LIMIT</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">5</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>&lt;=&gt;</code> operator computes cosine distance, which matches the HNSW index's <code>vector_cosine_ops</code> configuration. You can also use <code>&lt;-&gt;</code> for L2 (Euclidean) distance or <code>&lt;#&gt;</code> for inner product.</p>
<p>Combine vector search with standard SQL filters for hybrid queries:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">title</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embedding </span><span class="token operator" style="color:rgb(212, 212, 212)">&lt;=&gt;</span><span class="token plain"> $</span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">AS</span><span class="token plain"> distance</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> articles a</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">JOIN</span><span class="token plain"> articles_embeddings e </span><span class="token keyword" style="color:rgb(86, 156, 214)">ON</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">source_row_id::</span><span class="token keyword" style="color:rgb(86, 156, 214)">int</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">id</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">published </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">AND</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">category </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'technology'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">embedding </span><span class="token operator" style="color:rgb(212, 212, 212)">&lt;=&gt;</span><span class="token plain"> $</span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">LIMIT</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">10</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This is a key advantage of keeping embeddings in PostgreSQL rather than a separate vector database: your vectors and your relational data live in the same database, queryable in a single SQL statement.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-pipeline-status">Monitoring Pipeline Status<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#monitoring-pipeline-status" class="hash-link" aria-label="Direct link to Monitoring Pipeline Status" title="Direct link to Monitoring Pipeline Status">​</a></h2>
<p>Check how your pipeline is performing at any time:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:pass </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">service-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/embedding-pipelines/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">pipeline-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">|</span><span class="token plain"> jq </span><span class="token string" style="color:rgb(206, 145, 120)">'{status, rows_processed, rows_pending, tokens_used, last_processed_at, error_message}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response includes:</p>
<ul>
<li><strong><code>rows_processed</code></strong>: Total rows embedded since the pipeline was created.</li>
<li><strong><code>rows_pending</code></strong>: Rows waiting to be embedded (new inserts or updated text).</li>
<li><strong><code>tokens_used</code></strong>: Total tokens consumed by the model provider, useful for cost tracking.</li>
<li><strong><code>last_processed_at</code></strong>: Timestamp of the last successfully processed batch.</li>
<li><strong><code>error_message</code></strong>: Details when the pipeline enters <code>failed</code> state (e.g., invalid API key, provider rate limits, source table schema changes).</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="pausing-and-resuming">Pausing and Resuming<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#pausing-and-resuming" class="hash-link" aria-label="Direct link to Pausing and Resuming" title="Direct link to Pausing and Resuming">​</a></h2>
<p>Need to rotate your API key, or want to stop embedding during a bulk data migration? Pause the pipeline:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:pass </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">service-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/embedding-pipelines/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">pipeline-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/pause</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 worker completes any in-flight batch and stops. The companion table and its HNSW index are preserved. When you resume, the worker picks up where it left off and processes any rows that were inserted or updated while paused:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:pass </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">service-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/embedding-pipelines/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">pipeline-id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/resume</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="tuning-for-your-workload">Tuning for Your Workload<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#tuning-for-your-workload" class="hash-link" aria-label="Direct link to Tuning for Your Workload" title="Direct link to Tuning for Your Workload">​</a></h2>
<p>Two configuration knobs let you balance throughput, latency, and cost:</p>
<ul>
<li><strong><code>batch_size</code></strong> (1 to 1000, default 100): Larger batches reduce API call overhead but increase per-batch latency. Use smaller batches (10 to 50) for near-real-time applications, larger batches (200 to 1000) for bulk ingestion.</li>
<li><strong><code>poll_interval_seconds</code></strong> (5 to 3600, default 30): How frequently the worker checks for new or changed rows. A 5-second interval gives near-real-time embedding at the cost of higher CPU usage on the agent. A 300-second interval works well when freshness is less critical.</li>
</ul>
<p>Both can be updated on a running pipeline via the PATCH endpoint without pausing.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="limitations-worth-knowing">Limitations Worth Knowing<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#limitations-worth-knowing" class="hash-link" aria-label="Direct link to Limitations Worth Knowing" title="Direct link to Limitations Worth Knowing">​</a></h2>
<ul>
<li><strong>PostgreSQL only.</strong> Embedding pipelines require pgvector, which is a PostgreSQL extension.</li>
<li><strong>Primary node only.</strong> The embedding worker runs on the primary node. Read replicas do not run their own workers.</li>
<li><strong>One pipeline per source table.</strong> Each source table supports a single active pipeline. If you need different models for different use cases, use separate tables.</li>
<li><strong>Source table must have a primary key.</strong> The worker uses the primary key for row tracking and change detection.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-this-replaces">What This Replaces<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#what-this-replaces" class="hash-link" aria-label="Direct link to What This Replaces" title="Direct link to What This Replaces">​</a></h2>
<p>A typical DIY embedding pipeline involves a queue worker (or cron job), an embedding service wrapper, a database migration for the vector column and index, monitoring for the worker process, and retry/dead-letter logic for API failures. That is 200 to 500 lines of infrastructure code per table, plus ongoing operational burden.</p>
<p>With FoundryDB's managed pipelines, you replace all of that with a single POST request and a few configuration fields. The worker, the companion table, the HNSW index, the change detection, the batching, and the error handling are all managed for you.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://docs.foundrydb.com/blog/managed-embedding-pipelines-rag#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<ol>
<li><a href="https://docs.foundrydb.com/getting-started/" target="_blank" rel="noopener noreferrer">Create a PostgreSQL service</a> with pgvector enabled.</li>
<li><a href="https://docs.foundrydb.com/api/embedding-pipelines/" target="_blank" rel="noopener noreferrer">Create an embedding pipeline</a> via the API.</li>
<li>Insert data into your source table and watch the companion table populate automatically.</li>
<li>Query with pgvector operators and build your RAG application.</li>
</ol>
<p>If you are already running PostgreSQL on FoundryDB, you can add a pipeline to an existing service today. If you are new to the platform, the <code>agent-postgresql-rag</code> preset gives you a pgvector-ready database in under five minutes.</p>
<p><a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">Try FoundryDB</a> | <a href="https://docs.foundrydb.com/" target="_blank" rel="noopener noreferrer">Read the docs</a> | <a href="https://docs.foundrydb.com/api/embedding-pipelines/" target="_blank" rel="noopener noreferrer">Embedding Pipelines API reference</a></p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="embeddings" term="embeddings"/>
        <category label="rag" term="rag"/>
        <category label="pgvector" term="pgvector"/>
        <category label="openai" term="openai"/>
        <category label="cohere" term="cohere"/>
        <category label="ai" term="ai"/>
        <category label="vector-search" term="vector-search"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Why We Built FoundryDB on European Infrastructure]]></title>
        <id>https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure</id>
        <link href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[FoundryDB runs entirely on European cloud infrastructure. Here is why we chose UpCloud, how it affects your compliance, and what it means.]]></summary>
        <content type="html"><![CDATA[<p>When we started building FoundryDB, one of the first decisions was where to run the infrastructure. The answer shaped everything that followed: we chose to build exclusively on European cloud providers, starting with UpCloud, a Finnish infrastructure company operating under EU law.</p>
<p>This was not a marketing decision. It was a legal and architectural one. If you store customer data in databases, the jurisdiction of the infrastructure underneath those databases determines what legal regime governs access to that data. For many organizations in Europe, this distinction is no longer optional.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem-with-us-cloud-providers">The Problem with US Cloud Providers<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#the-problem-with-us-cloud-providers" class="hash-link" aria-label="Direct link to The Problem with US Cloud Providers" title="Direct link to The Problem with US Cloud Providers">​</a></h2>
<p>The US CLOUD Act (Clarifying Lawful Overseas Use of Data Act), passed in 2018, requires US-based cloud providers to comply with US government data requests regardless of where the data is physically stored. If your PostgreSQL database runs on AWS in Frankfurt, the data is physically in Germany, but Amazon is a US company. A US federal court can compel Amazon to hand over that data without going through European judicial channels.</p>
<p>This is not theoretical. Between 2019 and 2025, the number of disclosed CLOUD Act requests to major US providers grew steadily. The European Court of Justice invalidated the EU-US Privacy Shield in 2020 (Schrems II), and while the EU-US Data Privacy Framework was adopted in 2023, legal challenges continue. The fundamental tension remains: US surveillance law and EU privacy law have different priorities.</p>
<p>For companies subject to GDPR, DORA (Digital Operational Resilience Act for financial services), NIS2 (Network and Information Security Directive), or sector-specific regulations, this creates real compliance risk. Using a US cloud provider requires additional safeguards, legal analysis, and ongoing monitoring that many organizations would rather avoid entirely.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-upcloud">Why UpCloud<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#why-upcloud" class="hash-link" aria-label="Direct link to Why UpCloud" title="Direct link to Why UpCloud">​</a></h2>
<p>UpCloud is a Finnish company, headquartered in Helsinki, incorporated under Finnish law, with no US parent company or US legal obligations. This matters for one simple reason: a US court has no jurisdiction over UpCloud.</p>
<p>Here is what UpCloud brings to the table:</p>
<ul>
<li><strong>EU jurisdiction only</strong>: UpCloud operates under Finnish and EU law. Data stored on their infrastructure is subject to GDPR and Finnish data protection law. There is no legal mechanism for a US agency to compel UpCloud to produce data without going through EU legal processes (MLAT treaties), which include judicial review.</li>
<li><strong>ISO 27001 certified</strong>: information security management across all operations.</li>
<li><strong>SOC 2 Type II audited</strong>: independent verification of security controls.</li>
<li><strong>Data centers in 13 locations</strong>: 5 EU zones (Helsinki, Amsterdam, Frankfurt, Madrid, Warsaw) plus London, Singapore, Sydney, and others.</li>
<li><strong>100% SSD infrastructure</strong>: MaxIOPS storage delivers consistent low-latency performance for database workloads.</li>
</ul>
<p>We evaluated several European providers. UpCloud stood out for the combination of API maturity (a complete REST API for programmatic infrastructure management), performance (their MaxIOPS storage tier is genuinely fast), and geographic coverage within the EU.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-foundrydb-handles-data-residency">How FoundryDB Handles Data Residency<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#how-foundrydb-handles-data-residency" class="hash-link" aria-label="Direct link to How FoundryDB Handles Data Residency" title="Direct link to How FoundryDB Handles Data Residency">​</a></h2>
<p>Choosing a European cloud provider is necessary but not sufficient. The platform itself must enforce data residency guarantees. Here is how FoundryDB handles it.</p>
<p><strong>Data never leaves your chosen zone.</strong> When you create a service in <code>eu-helsinki</code>, your database, backups, replication traffic, and monitoring data all stay in the Helsinki data center. We do not replicate across zones unless you explicitly configure cross-zone replicas, and even then, both zones must be in the EU.</p>
<p><strong>Backups stay in-region.</strong> Automated backups and point-in-time recovery archives are stored in object storage within the same geographic region as your database. A PostgreSQL service in Frankfurt has its WAL archives and base backups in EU-based storage.</p>
<p><strong>No transatlantic telemetry.</strong> FoundryDB's monitoring, alerting, and metrics infrastructure runs within the EU. Your query statistics, performance metrics, and alert history do not cross the Atlantic.</p>
<p><strong>TLS everywhere.</strong> All connections (client to database, database to database, agent to controller) are encrypted with TLS. Certificates are provisioned automatically via Let's Encrypt.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="compliance-alignment">Compliance Alignment<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#compliance-alignment" class="hash-link" aria-label="Direct link to Compliance Alignment" title="Direct link to Compliance Alignment">​</a></h2>
<p>FoundryDB's architecture on European infrastructure aligns with several regulatory frameworks.</p>
<p><strong>GDPR (General Data Protection Regulation)</strong>: Article 44 restricts transfers of personal data to countries without adequate protection. By keeping all data within the EU on a provider with no US legal obligations, FoundryDB eliminates the need for Standard Contractual Clauses or Transfer Impact Assessments related to US cloud providers.</p>
<p><strong>DORA (Digital Operational Resilience Act)</strong>: Effective January 2025, DORA requires financial entities to manage ICT third-party risk, including ensuring that critical infrastructure providers do not introduce concentration risk or jurisdictional concerns. Using a European provider removes one layer of that risk.</p>
<p><strong>NIS2 (Network and Information Security Directive 2)</strong>: NIS2 broadens cybersecurity obligations across essential and important entities. The directive emphasizes supply chain security and the need to assess the legal environment of third-party providers.</p>
<p><strong>Schrems II implications</strong>: The Schrems II ruling did not just invalidate Privacy Shield. It also raised the bar for Standard Contractual Clauses by requiring organizations to assess whether the legal framework in the recipient country provides adequate protection. For US transfers, this assessment is difficult to pass. With FoundryDB, the assessment is straightforward: data stays in the EU, provider is EU-based, EU law applies.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-happens-when-an-agency-requests-your-data">What Happens When an Agency Requests Your Data<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#what-happens-when-an-agency-requests-your-data" class="hash-link" aria-label="Direct link to What Happens When an Agency Requests Your Data" title="Direct link to What Happens When an Agency Requests Your Data">​</a></h2>
<p>Consider two scenarios.</p>
<p><strong>Scenario A: Your database is on AWS Frankfurt.</strong> A US federal agency serves a warrant to Amazon under the CLOUD Act. Amazon is required to comply. Your data is produced without EU judicial oversight. You may not even be notified, depending on the type of order.</p>
<p><strong>Scenario B: Your database is on FoundryDB (UpCloud Helsinki).</strong> A US federal agency wants your data. They have no jurisdiction over UpCloud. They must go through the Finnish legal system via MLAT (Mutual Legal Assistance Treaty). This requires a request to Finnish authorities, who evaluate it under Finnish law, including EU fundamental rights. The process includes judicial review, and your organization may be notified.</p>
<p>The difference is not about whether law enforcement can ever access data. It is about whether the process includes proper legal safeguards and EU judicial oversight.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-business-case">The Business Case<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#the-business-case" class="hash-link" aria-label="Direct link to The Business Case" title="Direct link to The Business Case">​</a></h2>
<p>European data sovereignty is not just about compliance. It is increasingly a competitive differentiator.</p>
<p>Enterprise procurement teams in the EU now regularly include data residency and jurisdictional requirements in RFPs. We have seen organizations willing to pay a 15-30% premium for services that guarantee EU-only infrastructure, because the alternative (the legal overhead of managing US cloud provider compliance, ongoing monitoring of adequacy decisions, Transfer Impact Assessments, supplementary measures) costs more in legal fees and organizational effort.</p>
<p>For SaaS companies selling to European enterprises, being able to say "your data is stored on EU infrastructure with no US jurisdictional exposure" simplifies sales cycles. It removes a procurement blocker that can add weeks or months to deal closure.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="available-zones">Available Zones<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#available-zones" class="hash-link" aria-label="Direct link to Available Zones" title="Direct link to Available Zones">​</a></h2>
<p>FoundryDB currently offers services in the following EU zones:</p>
<table><thead><tr><th>Zone</th><th>Location</th><th>Identifier</th></tr></thead><tbody><tr><td>Helsinki</td><td>Finland</td><td><code>eu-helsinki</code></td></tr><tr><td>Amsterdam</td><td>Netherlands</td><td><code>eu-amsterdam</code></td></tr><tr><td>Frankfurt</td><td>Germany</td><td><code>eu-frankfurt</code></td></tr><tr><td>Madrid</td><td>Spain</td><td><code>eu-madrid</code></td></tr><tr><td>Warsaw</td><td>Poland</td><td><code>eu-warsaw</code></td></tr></tbody></table>
<p>All zones support all database engines (PostgreSQL, MySQL, MongoDB, Valkey, Kafka) with the same feature set. Cross-zone read replicas are available for PostgreSQL and MySQL within EU zones.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="our-commitment">Our Commitment<a href="https://docs.foundrydb.com/blog/why-we-built-foundrydb-on-european-infrastructure#our-commitment" class="hash-link" aria-label="Direct link to Our Commitment" title="Direct link to Our Commitment">​</a></h2>
<p>European infrastructure is not a feature we bolt on. It is the foundation of FoundryDB. Every architecture decision, from backup storage locations to monitoring infrastructure to DNS resolution, is designed around the principle that your data stays in Europe under European law.</p>
<p>We believe that managed database services should not force you to choose between operational convenience and regulatory compliance. You should get both.</p>
<p>To learn more about FoundryDB's security and compliance posture, visit our <a href="https://docs.foundrydb.com/security/overview">Security overview</a>. To deploy your first database on European infrastructure, follow the <a href="https://docs.foundrydb.com/getting-started/quick-start">quick start guide</a>.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="infrastructure" term="infrastructure"/>
        <category label="gdpr" term="gdpr"/>
        <category label="compliance" term="compliance"/>
        <category label="europe" term="europe"/>
        <category label="security" term="security"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Event Streaming with Managed Kafka: Patterns That Scale]]></title>
        <id>https://docs.foundrydb.com/blog/kafka-event-streaming-patterns</id>
        <link href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Practical patterns for event-driven architectures using managed Kafka on FoundryDB. Covers topic design, partitioning strategies, consumer groups, and Schema Registry.]]></summary>
        <content type="html"><![CDATA[<p>Event-driven architecture has moved from buzzword to baseline. If you are building microservices, real-time analytics, or data pipelines in 2026, Kafka is likely somewhere in the stack. The challenge is not whether to use it, but how to operate it without drowning in ZooKeeper configs, TLS certificate rotation, and broker rebalancing.</p>
<p>This post covers practical streaming patterns on FoundryDB's managed Kafka: topic design, partitioning strategies, consumer groups, schema enforcement, and monitoring. All examples use FoundryDB's Kafka 4.0 with KRaft mode and SASL/SCRAM authentication.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-managed-kafka">Why Managed Kafka<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#why-managed-kafka" class="hash-link" aria-label="Direct link to Why Managed Kafka" title="Direct link to Why Managed Kafka">​</a></h2>
<p>Running Kafka in production has historically meant managing ZooKeeper quorums, rolling broker upgrades, and debugging ISR shrinkage at 2 AM. FoundryDB removes that overhead entirely.</p>
<p>Every Kafka service on FoundryDB runs in <strong>KRaft mode</strong> (no ZooKeeper dependency), with <strong>SASL/SCRAM-SHA-256</strong> authentication enabled by default and <strong>TLS</strong> on all client connections. You get per-topic ACLs, automated backups, consumer lag monitoring, and broker scaling through a single API. Provisioning takes under five minutes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="provisioning-a-kafka-service">Provisioning a Kafka Service<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#provisioning-a-kafka-service" class="hash-link" aria-label="Direct link to Provisioning a Kafka Service" title="Direct link to Provisioning a Kafka Service">​</a></h2>
<p>A single API call creates a production-ready Kafka cluster. The CLI works just as well.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Via CLI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services create </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--name</span><span class="token plain"> events-prod </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--engine</span><span class="token plain"> kafka </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">4.0</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--plan</span><span class="token plain"> tier-4 </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--storage</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">200</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  --storage-tier maxiops </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Via API</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "name": "events-prod",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_type": "kafka",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "version": "4.0",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-4",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_size_gb": 200,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_tier": "maxiops",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "eu-helsinki"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Once the service is running, grab your bootstrap server and SASL credentials from <code>fdb services get events-prod --format json</code>. Every example below assumes these are set as environment variables.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="topic-design-patterns">Topic Design Patterns<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#topic-design-patterns" class="hash-link" aria-label="Direct link to Topic Design Patterns" title="Direct link to Topic Design Patterns">​</a></h2>
<p>Topic design is where most Kafka architectures succeed or fail. A poorly designed topic forces you into expensive rework later. Three patterns cover the majority of use cases.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="event-sourcing">Event Sourcing<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#event-sourcing" class="hash-link" aria-label="Direct link to Event Sourcing" title="Direct link to Event Sourcing">​</a></h3>
<p>Store every state change as an immutable event. The topic becomes your system of record, and current state is derived by replaying events.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/kafka/topics </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "name": "orders.events",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "partitions": 12,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "replication_factor": 3,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "config": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "cleanup.policy": "compact",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "retention.ms": "-1",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "min.insync.replicas": "2"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Use <code>cleanup.policy: compact</code> with infinite retention. Kafka keeps the latest value for each key, so your topic does not grow unbounded while still preserving the full current state.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="change-data-capture-cdc">Change Data Capture (CDC)<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#change-data-capture-cdc" class="hash-link" aria-label="Direct link to Change Data Capture (CDC)" title="Direct link to Change Data Capture (CDC)">​</a></h3>
<p>Capture row-level changes from a source database and stream them into Kafka. Each topic mirrors a table: <code>cdc.public.users</code>, <code>cdc.public.orders</code>. Consumers build materialized views, update search indexes, or sync data warehouses.</p>
<p>Use <code>cleanup.policy: delete</code> with a retention window that matches your recovery SLA (7 to 30 days is typical). Partition by the table's primary key so all changes to a given row land on the same partition in order.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="commandquery-separation-cqrs">Command/Query Separation (CQRS)<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#commandquery-separation-cqrs" class="hash-link" aria-label="Direct link to Command/Query Separation (CQRS)" title="Direct link to Command/Query Separation (CQRS)">​</a></h3>
<p>Separate write-side commands from read-side queries using dedicated topics. Commands like <code>payments.commands</code> carry intent ("charge this card"), while events like <code>payments.events</code> carry facts ("payment succeeded"). This decouples write validation from read model updates and lets each side scale independently.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="partitioning-strategies">Partitioning Strategies<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#partitioning-strategies" class="hash-link" aria-label="Direct link to Partitioning Strategies" title="Direct link to Partitioning Strategies">​</a></h2>
<p>Partitions are the unit of parallelism in Kafka. The partition key determines which partition a message lands on, and getting it right is critical for ordering guarantees and even load distribution.</p>
<table><thead><tr><th>Strategy</th><th>Partition Key</th><th>Ordering Guarantee</th><th>Best For</th></tr></thead><tbody><tr><td><strong>By entity ID</strong></td><td><code>order_id</code>, <code>user_id</code></td><td>All events for one entity in order</td><td>Event sourcing, CDC</td></tr><tr><td><strong>By tenant</strong></td><td><code>tenant_id</code></td><td>All events for one tenant in order</td><td>Multi-tenant SaaS</td></tr><tr><td><strong>Round-robin</strong></td><td><code>null</code> (no key)</td><td>None</td><td>Logs, metrics, high-throughput analytics</td></tr></tbody></table>
<p><strong>By entity ID</strong> is the most common choice. It guarantees that all events for a given order or user arrive at the same consumer in sequence, which is essential for correct state reconstruction.</p>
<p><strong>By tenant</strong> works well for SaaS platforms where you need tenant-level ordering but want to spread load across partitions. Watch out for hot partitions if one tenant produces disproportionately more traffic.</p>
<p><strong>Round-robin</strong> (null key) maximizes throughput by distributing messages evenly, but sacrifices ordering. Use it only when message order does not matter.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="consumer-groups-and-exactly-once-semantics">Consumer Groups and Exactly-Once Semantics<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#consumer-groups-and-exactly-once-semantics" class="hash-link" aria-label="Direct link to Consumer Groups and Exactly-Once Semantics" title="Direct link to Consumer Groups and Exactly-Once Semantics">​</a></h2>
<p>Consumer groups let you scale processing horizontally. Kafka assigns each partition to exactly one consumer within a group, so adding consumers (up to the partition count) increases throughput linearly.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)"># Monitor consumer lag via the FoundryDB API</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/kafka/consumer-groups/order-processors/lag</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>For exactly-once processing, combine Kafka's idempotent producer with transactional consumers. The producer assigns sequence numbers to each message, and the consumer commits offsets within a transaction alongside its output writes. In Java:</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">Properties props = new Properties();</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">props.put("bootstrap.servers", System.getenv("KAFKA_BOOTSTRAP"));</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">props.put("security.protocol", "SASL_SSL");</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">props.put("sasl.mechanism", "SCRAM-SHA-256");</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">props.put("sasl.jaas.config",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    "org.apache.kafka.common.security.scram.ScramLoginModule required "</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    + "username=\"" + System.getenv("KAFKA_USER") + "\" "</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    + "password=\"" + System.getenv("KAFKA_PASSWORD") + "\";");</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">// Exactly-once producer</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">props.put("enable.idempotence", "true");</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">props.put("transactional.id", "order-processor-1");</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">props.put("acks", "all");</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">KafkaProducer&lt;String, String&gt; producer = new KafkaProducer&lt;&gt;(props);</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">producer.initTransactions();</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 key settings are <code>enable.idempotence: true</code>, <code>acks: all</code>, and a stable <code>transactional.id</code>. On the broker side, FoundryDB defaults to <code>min.insync.replicas: 2</code>, so <code>acks=all</code> requires at least two brokers to acknowledge before a write is considered committed.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="schema-registry-for-contract-enforcement">Schema Registry for Contract Enforcement<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#schema-registry-for-contract-enforcement" class="hash-link" aria-label="Direct link to Schema Registry for Contract Enforcement" title="Direct link to Schema Registry for Contract Enforcement">​</a></h2>
<p>As your topic count grows, schema drift becomes a real problem. A producer changes a field name, and three downstream consumers break silently. Schema Registry enforces contracts between producers and consumers.</p>
<p>FoundryDB supports Confluent-compatible Schema Registry. Register Avro or JSON Schema definitions, and the serializer validates every message before it hits the broker.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> confluent_kafka </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> Producer</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> confluent_kafka</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">schema_registry </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> SchemaRegistryClient</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> confluent_kafka</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">schema_registry</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">avro </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> AvroSerializer</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">schema_registry </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> SchemaRegistryClient</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"url"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"https://events-prod.db.foundrydb.com:8081"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">order_schema </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">"""{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">  "type": "record",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">  "name": "OrderEvent",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">  "fields": [</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">    {"name": "order_id", "type": "string"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">    {"name": "status", "type": {"type": "enum", "name": "Status",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">      "symbols": ["CREATED", "PAID", "SHIPPED", "DELIVERED"]}},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">    {"name": "amount_cents", "type": "long"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">    {"name": "timestamp", "type": {"type": "long", "logicalType": "timestamp-millis"}}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">  ]</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token triple-quoted-string string" style="color:rgb(206, 145, 120)">}"""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">serializer </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> AvroSerializer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">schema_registry</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> order_schema</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">producer </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> Producer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"bootstrap.servers"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"events-prod.db.foundrydb.com:9093"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"security.protocol"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"SASL_SSL"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"sasl.mechanisms"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"SCRAM-SHA-256"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"sasl.username"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"order-service"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"sasl.password"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"your-password"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">producer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">produce</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    topic</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"orders.events"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    key</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"order-12345"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    value</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain">serializer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string" style="color:rgb(206, 145, 120)">"order_id"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"order-12345"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"status"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"CREATED"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">                       </span><span class="token string" style="color:rgb(206, 145, 120)">"amount_cents"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">4999</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"timestamp"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1775212800000</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">producer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">flush</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Set schema compatibility to <code>BACKWARD</code> (the default) so consumers using older schemas can still read messages produced with newer schemas. This lets you evolve schemas safely by adding optional fields without breaking existing consumers.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-what-to-watch">Monitoring: What to Watch<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#monitoring-what-to-watch" class="hash-link" aria-label="Direct link to Monitoring: What to Watch" title="Direct link to Monitoring: What to Watch">​</a></h2>
<p>Two metrics matter more than all others for Kafka operations.</p>
<p><strong>Consumer lag</strong> measures how far behind a consumer group is from the latest offset. Rising lag means consumers cannot keep up with producers. The fix is usually more consumer instances (up to your partition count) or faster processing logic. Monitor via the FoundryDB API:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"https://api.foundrydb.com/managed-services/{id}/metrics?metric=consumer_lag&amp;period=1h"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Under-replicated partitions</strong> indicates brokers that have fallen behind the leader. A non-zero count means your cluster is at risk of data loss if another broker fails. In a managed environment, FoundryDB handles broker recovery automatically, but this metric is still worth alerting on. A sustained non-zero value warrants a support ticket.</p>
<p>Other metrics to track: <code>messages_in_per_sec</code> (throughput), <code>bytes_in_per_sec</code> and <code>bytes_out_per_sec</code> (network saturation), and disk usage (plan your retention window accordingly).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="connecting-with-saslscram">Connecting with SASL/SCRAM<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#connecting-with-saslscram" class="hash-link" aria-label="Direct link to Connecting with SASL/SCRAM" title="Direct link to Connecting with SASL/SCRAM">​</a></h2>
<p>Every Kafka client needs four things: bootstrap server, security protocol, SASL mechanism, and credentials. Here is a minimal Python consumer for reference:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">from</span><span class="token plain"> kafka </span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> KafkaConsumer</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">consumer </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> KafkaConsumer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"orders.events"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    bootstrap_servers</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"events-prod.db.foundrydb.com:9093"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    security_protocol</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"SASL_SSL"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    sasl_mechanism</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"SCRAM-SHA-256"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    sasl_plain_username</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"order-analytics"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    sasl_plain_password</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"your-password"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    group_id</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"analytics-workers"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    auto_offset_reset</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"earliest"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    value_deserializer</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token keyword" style="color:rgb(86, 156, 214)">lambda</span><span class="token plain"> m</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">m</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">decode</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">"utf-8"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">for</span><span class="token plain"> message </span><span class="token keyword" style="color:rgb(86, 156, 214)">in</span><span class="token plain"> consumer</span><span class="token punctuation" style="color:rgb(212, 212, 212)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">print</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">f"Partition </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string-interpolation interpolation">message</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token string-interpolation interpolation">partition</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">, Offset </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string-interpolation interpolation">message</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token string-interpolation interpolation">offset</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token string-interpolation interpolation">message</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token string-interpolation interpolation">value</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token string-interpolation string" style="color:rgb(206, 145, 120)">"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 bootstrap port is always <code>9093</code> for SASL connections. Port <code>9092</code> is reserved for internal broker communication and is not exposed to clients.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://docs.foundrydb.com/blog/kafka-event-streaming-patterns#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps">​</a></h2>
<p>Start with one topic and one consumer group. Get the partitioning strategy right, enforce schemas early, and monitor consumer lag from day one. Retrofitting these patterns into an existing system is significantly harder than building them in from the start.</p>
<p>Create your first Kafka service on FoundryDB in under five minutes with the <a href="https://docs.foundrydb.com/getting-started/quick-start">quick start guide</a>, or dive into the full <a href="https://docs.foundrydb.com/databases/kafka">Kafka documentation</a> for topic management, ACLs, and broker scaling. If you are building event-driven microservices, the <a href="https://docs.foundrydb.com/blog/build-rag-pipeline-postgresql-pgvector-kafka">RAG pipeline tutorial</a> shows how Kafka integrates with PostgreSQL and Valkey on the same platform.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="kafka" term="kafka"/>
        <category label="event-streaming" term="event-streaming"/>
        <category label="architecture" term="architecture"/>
        <category label="schema-registry" term="schema-registry"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[MCP Server: Connecting AI Coding Assistants to Your Databases]]></title>
        <id>https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants</id>
        <link href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[FoundryDB's MCP server lets AI assistants like Claude, Cursor, and Windsurf provision databases, query data, and manage backups through natural conversation. Install in one command.]]></summary>
        <content type="html"><![CDATA[<p>Your AI coding assistant can write SQL, generate migrations, and debug queries. But when you need a database to run that code against, you leave the conversation, open a dashboard, click through a provisioning wizard, copy credentials back into your editor, and resume. That context switch breaks flow.</p>
<p>FoundryDB's MCP server removes it. Your AI assistant provisions databases, retrieves connection strings, checks metrics, and triggers backups without you ever leaving the conversation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-mcp">What Is MCP?<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#what-is-mcp" class="hash-link" aria-label="Direct link to What Is MCP?" title="Direct link to What Is MCP?">​</a></h2>
<p>The Model Context Protocol (MCP) is an open standard that lets AI assistants call external tools. Instead of the assistant generating code for you to copy and run, MCP lets it execute actions directly: create a database, fetch logs, list backups. The assistant sends a structured tool call, the MCP server executes it against the FoundryDB API, and the result comes back into the conversation.</p>
<p>MCP is supported by Claude (Anthropic), Cursor, Windsurf, and a growing list of AI coding tools. If your assistant supports MCP, it can use the FoundryDB server.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-the-foundrydb-mcp-server-provides">What the FoundryDB MCP Server Provides<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#what-the-foundrydb-mcp-server-provides" class="hash-link" aria-label="Direct link to What the FoundryDB MCP Server Provides" title="Direct link to What the FoundryDB MCP Server Provides">​</a></h2>
<p>The server exposes 13 tools across four categories. Every tool maps to a real FoundryDB API operation. Here is the full list, pulled directly from the implementation.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="service-management-7-tools">Service Management (7 tools)<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#service-management-7-tools" class="hash-link" aria-label="Direct link to Service Management (7 tools)" title="Direct link to Service Management (7 tools)">​</a></h3>
<table><thead><tr><th>Tool</th><th>Description</th></tr></thead><tbody><tr><td><code>list_organizations</code></td><td>List all organizations the authenticated user belongs to</td></tr><tr><td><code>list_services</code></td><td>List all managed database services with status, type, zone, and plan</td></tr><tr><td><code>get_service</code></td><td>Get full details of a service by UUID or name</td></tr><tr><td><code>create_service</code></td><td>Provision a new database (PostgreSQL, MySQL, MongoDB, Valkey, Kafka, OpenSearch, or SQL Server)</td></tr><tr><td><code>delete_service</code></td><td>Permanently delete a service and all its data</td></tr><tr><td><code>get_service_nodes</code></td><td>List all nodes (primary and replicas) with roles, status, and VM details</td></tr><tr><td><code>list_presets</code></td><td>List available AI agent presets for one-call provisioning</td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="database-users-3-tools">Database Users (3 tools)<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#database-users-3-tools" class="hash-link" aria-label="Direct link to Database Users (3 tools)" title="Direct link to Database Users (3 tools)">​</a></h3>
<table><thead><tr><th>Tool</th><th>Description</th></tr></thead><tbody><tr><td><code>list_users</code></td><td>List all database users for a service</td></tr><tr><td><code>reveal_password</code></td><td>Reveal the password for a specific database user</td></tr><tr><td><code>get_connection_string</code></td><td>Get a ready-to-use connection string in multiple formats: <code>url</code>, <code>env</code>, <code>psql</code>, <code>mysql</code>, <code>mongosh</code>, or <code>redis-cli</code></td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="backups-2-tools">Backups (2 tools)<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#backups-2-tools" class="hash-link" aria-label="Direct link to Backups (2 tools)" title="Direct link to Backups (2 tools)">​</a></h3>
<table><thead><tr><th>Tool</th><th>Description</th></tr></thead><tbody><tr><td><code>list_backups</code></td><td>List all backups for a service, including scheduled and on-demand</td></tr><tr><td><code>trigger_backup</code></td><td>Trigger an immediate on-demand backup (full, incremental, or PITR)</td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-2-tools">Monitoring (2 tools)<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#monitoring-2-tools" class="hash-link" aria-label="Direct link to Monitoring (2 tools)" title="Direct link to Monitoring (2 tools)">​</a></h3>
<table><thead><tr><th>Tool</th><th>Description</th></tr></thead><tbody><tr><td><code>get_metrics</code></td><td>Get current CPU, memory, storage, and connection metrics</td></tr><tr><td><code>get_logs</code></td><td>Retrieve recent database logs (up to 1,000 lines)</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="installation">Installation<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#installation" class="hash-link" aria-label="Direct link to Installation" title="Direct link to Installation">​</a></h2>
<p>The MCP server is distributed as a Go binary. Configure it in your assistant's MCP settings with three environment variables.</p>
<p>For <strong>Claude Desktop</strong>, add this to your <code>claude_desktop_config.json</code>:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"mcpServers"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token property">"foundrydb"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"foundrydb-mcp"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"env"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token property">"FOUNDRYDB_API_URL"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"https://api.foundrydb.com"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token property">"FOUNDRYDB_USERNAME"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"your-username"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">        </span><span class="token property">"FOUNDRYDB_PASSWORD"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"your-password"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>For <strong>Cursor</strong>, add the same configuration to your <code>.cursor/mcp.json</code>.</p>
<p>The server communicates over stdio, which is the standard MCP transport. No ports to open, no daemons to manage.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="example-conversations">Example Conversations<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#example-conversations" class="hash-link" aria-label="Direct link to Example Conversations" title="Direct link to Example Conversations">​</a></h2>
<p>Here is what working with the MCP server looks like in practice.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="provisioning-a-database-for-a-new-project">Provisioning a database for a new project<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#provisioning-a-database-for-a-new-project" class="hash-link" aria-label="Direct link to Provisioning a database for a new project" title="Direct link to Provisioning a database for a new project">​</a></h3>
<blockquote>
<p><strong>You:</strong> I need a PostgreSQL 17 database for the new recommendation service. Use tier-2 in Stockholm with 50 GB storage.</p>
<p><strong>Assistant</strong> calls <code>create_service</code> with <code>name: "recommendation-svc"</code>, <code>database_type: "postgresql"</code>, <code>version: "17"</code>, <code>plan_name: "tier-2"</code>, <code>zone: "se-sto1"</code>, <code>storage_size_gb: 50</code>.</p>
<p><strong>Assistant:</strong> Created service <code>recommendation-svc</code> (ID: <code>a1b2c3d4-...</code>). It will be ready in about 5 minutes. Want me to check the status?</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="getting-connection-credentials">Getting connection credentials<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#getting-connection-credentials" class="hash-link" aria-label="Direct link to Getting connection credentials" title="Direct link to Getting connection credentials">​</a></h3>
<blockquote>
<p><strong>You:</strong> The recommendation service should be ready now. Get me the psql connection string.</p>
<p><strong>Assistant</strong> calls <code>get_service</code> with <code>name: "recommendation-svc"</code>, then <code>list_users</code> and <code>get_connection_string</code> with <code>format: "psql"</code>.</p>
<p><strong>Assistant:</strong> Here is your connection command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">psql </span><span class="token string" style="color:rgb(206, 145, 120)">"postgres://app_user:abc123@rec-svc.db.foundrydb.com:5432/defaultdb?sslmode=verify-full"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="checking-health-during-an-incident">Checking health during an incident<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#checking-health-during-an-incident" class="hash-link" aria-label="Direct link to Checking health during an incident" title="Direct link to Checking health during an incident">​</a></h3>
<blockquote>
<p><strong>You:</strong> The app is slow. Check the database metrics and recent logs.</p>
<p><strong>Assistant</strong> calls <code>get_metrics</code> and <code>get_logs</code> with <code>lines: 200</code>.</p>
<p><strong>Assistant:</strong> CPU is at 89%, connections are at 147/200. The logs show several slow queries on the <code>embeddings</code> table. The longest took 12 seconds. Want me to pull the specific queries?</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="creating-ephemeral-databases-for-ai-agents">Creating ephemeral databases for AI agents<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#creating-ephemeral-databases-for-ai-agents" class="hash-link" aria-label="Direct link to Creating ephemeral databases for AI agents" title="Direct link to Creating ephemeral databases for AI agents">​</a></h3>
<p>The <code>create_service</code> tool supports AI-specific parameters that make it useful for agent orchestration, not just human conversations.</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">create_service({</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  name: "langchain-rag-run-482",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  preset: "agent-postgresql-rag",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  ttl_hours: 24,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  is_ephemeral: true,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  agent_framework: "langchain",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  agent_purpose: "rag"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">})</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This creates a PostgreSQL instance with pgvector pre-configured, labels it with the agent framework and purpose, and auto-deletes it after 24 hours. The <code>list_presets</code> tool shows all available presets, including <code>agent-mongodb-conversation</code>, <code>agent-valkey-session</code>, and <code>agent-kafka-events</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="security-model">Security Model<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#security-model" class="hash-link" aria-label="Direct link to Security Model" title="Direct link to Security Model">​</a></h2>
<p>The MCP server authenticates to the FoundryDB API using username/password credentials set via environment variables. Both <code>FOUNDRYDB_USERNAME</code> and <code>FOUNDRYDB_PASSWORD</code> are required. The server refuses to start if either is missing, which prevents accidental runs with default credentials.</p>
<p>All tool calls go through the same authentication, authorization, and audit logging as direct API calls. The MCP server is a thin client that wraps the <a href="https://github.com/foundrydb/foundrydb-sdk-go" target="_blank" rel="noopener noreferrer">Go SDK</a>. It does not bypass any access controls.</p>
<p>A few things to keep in mind:</p>
<ul>
<li><strong>Destructive operations require confirmation.</strong> Tools like <code>delete_service</code> and <code>trigger_backup</code> modify state. Your AI assistant will typically ask for confirmation before calling them, since the tool descriptions clearly indicate irreversible actions (e.g., "Permanently delete a managed database service and all its data. This action cannot be undone.").</li>
<li><strong>Credentials stay local.</strong> The MCP server runs on your machine, communicating with your assistant over stdio. Your FoundryDB credentials are never sent to the AI model itself.</li>
<li><strong>Organization scoping.</strong> The <code>create_service</code> tool accepts an <code>organization_id</code> parameter. When provided, the server creates an org-scoped API client, ensuring the service is provisioned in the correct organization.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-works-under-the-hood">How It Works Under the Hood<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#how-it-works-under-the-hood" class="hash-link" aria-label="Direct link to How It Works Under the Hood" title="Direct link to How It Works Under the Hood">​</a></h2>
<p>The MCP server is built with the <a href="https://github.com/mark3labs/mcp-go" target="_blank" rel="noopener noreferrer"><code>mcp-go</code></a> library and the <a href="https://github.com/foundrydb/foundrydb-sdk-go" target="_blank" rel="noopener noreferrer">FoundryDB Go SDK</a>. Each tool is a function that validates inputs, calls the SDK, and returns formatted JSON. The server runs as a stdio process that the AI assistant manages.</p>
<p>For endpoints not yet covered by the SDK (like metrics and logs), the server makes direct authenticated HTTP calls to the API. Log retrieval is async: the server triggers the fetch, then polls for results with a 60-second timeout, so the assistant gets the logs without the user needing to wait and retry.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://docs.foundrydb.com/blog/mcp-server-ai-coding-assistants#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<ol>
<li>Install the MCP server from <a href="https://github.com/foundrydb/foundrydb-mcp" target="_blank" rel="noopener noreferrer">github.com/foundrydb/foundrydb-mcp</a></li>
<li>Configure your assistant with your FoundryDB credentials</li>
<li>Ask your assistant to <code>list_services</code> and see what comes back</li>
</ol>
<p>If you do not have a FoundryDB account yet, <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">sign up at foundrydb.com</a> and you will have a database running in under five minutes. Check the <a href="https://docs.foundrydb.com/" target="_blank" rel="noopener noreferrer">documentation</a> for full API reference and guides.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="mcp" term="mcp"/>
        <category label="ai" term="ai"/>
        <category label="claude" term="claude"/>
        <category label="cursor" term="cursor"/>
        <category label="windsurf" term="windsurf"/>
        <category label="model-context-protocol" term="model-context-protocol"/>
        <category label="developer-tools" term="developer-tools"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[MongoDB on FoundryDB: Aggregation Pipelines, Replica Sets, and Point-in-Time Recovery]]></title>
        <id>https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr</id>
        <link href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Run production MongoDB with automated replica sets, oplog-based PITR, and WiredTiger tuning. Practical guide with aggregation pipeline examples and disaster recovery workflows.]]></summary>
        <content type="html"><![CDATA[<p>MongoDB is one of the most popular document databases in the world, but running it in production comes with real operational overhead: replica set initialization, oplog sizing, backup orchestration, WiredTiger cache tuning, and disaster recovery planning. FoundryDB handles all of this out of the box, so you can focus on your application logic.</p>
<p>This post walks through provisioning a MongoDB service, running aggregation pipelines against it, and recovering from data loss using oplog-based point-in-time recovery.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="provision-a-mongodb-service">Provision a MongoDB Service<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#provision-a-mongodb-service" class="hash-link" aria-label="Direct link to Provision a MongoDB Service" title="Direct link to Provision a MongoDB Service">​</a></h2>
<p>A single API call creates a 3-member replica set with TLS, automated backups, and continuous oplog archiving. No SSH, no config files, no manual <code>rs.initiate()</code>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "name": "analytics-mongo",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_type": "mongodb",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "version": "8",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "se-sto1",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_size_gb": 50,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_tier": "maxiops"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 service transitions from <code>pending</code> through <code>provisioning</code> to <code>running</code> in under five minutes. Once running, connect with the replica set name for full topology awareness:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">mongosh </span><span class="token string" style="color:rgb(206, 145, 120)">"mongodb://USER:PASS@analytics-mongo.db.foundrydb.com:27017/defaultdb?tls=true&amp;replicaSet=rs0"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Every node runs on dedicated infrastructure with a 3-disk architecture: OS disk, NVMe data disk, and a separate backup disk. The data disk uses <code>maxiops</code> storage, which gives consistent low-latency I/O for write-heavy MongoDB workloads.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="replica-set-topology">Replica Set Topology<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#replica-set-topology" class="hash-link" aria-label="Direct link to Replica Set Topology" title="Direct link to Replica Set Topology">​</a></h2>
<p>All MongoDB services on FoundryDB deploy as a 3-member replica set using the <code>rs0</code> replica set name. The platform handles:</p>
<ul>
<li><strong>Automatic <code>rs.initiate()</code></strong> on the primary during provisioning</li>
<li><strong><code>rs.add()</code> for secondaries</strong> using shared keyFile authentication (SCRAM-SHA-1)</li>
<li><strong>Automatic failover</strong> within approximately 10 seconds if the primary goes down</li>
<li><strong>Read preference routing</strong> via your driver (<code>secondaryPreferred</code>, <code>nearest</code>)</li>
</ul>
<p>If you need higher read throughput, scale to a 5-member replica set with one API call:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"role": "replica"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 also trigger a manual failover to a specific secondary for maintenance or testing:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">node_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/failover</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="aggregation-pipeline-examples">Aggregation Pipeline Examples<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#aggregation-pipeline-examples" class="hash-link" aria-label="Direct link to Aggregation Pipeline Examples" title="Direct link to Aggregation Pipeline Examples">​</a></h2>
<p>With the service running, let's look at some practical aggregation pipelines. These examples assume you have an <code>orders</code> collection with documents like:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"userId"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"u_1234"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"items"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token property">"product"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Widget A"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"tools"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">29.99</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"qty"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token property">"product"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Widget B"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"parts"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">14.50</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token property">"qty"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"createdAt"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token property">"$date"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-03-15T10:30:00Z"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"completed"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="revenue-by-category-with-unwind-group-and-sort">Revenue by Category with $unwind, $group, and $sort<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#revenue-by-category-with-unwind-group-and-sort" class="hash-link" aria-label="Direct link to Revenue by Category with $unwind, $group, and $sort" title="Direct link to Revenue by Category with $unwind, $group, and $sort">​</a></h3>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token property-access">orders</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">aggregate</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$match</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">status</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"completed"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token literal-property property">createdAt</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$gte</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(220, 220, 170)">ISODate</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">"2026-01-01"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$unwind</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$items"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$items.category"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">totalRevenue</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$multiply</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"$items.price"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$items.qty"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">orderCount</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">avgOrderValue</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$avg</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$multiply</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">"$items.price"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$items.qty"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">totalRevenue</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">-</span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$limit</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">10</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="customer-lifetime-value-with-lookup">Customer Lifetime Value with $lookup<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#customer-lifetime-value-with-lookup" class="hash-link" aria-label="Direct link to Customer Lifetime Value with $lookup" title="Direct link to Customer Lifetime Value with $lookup">​</a></h3>
<p>Join <code>orders</code> with a <code>customers</code> collection to compute per-customer metrics:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token property-access">orders</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">aggregate</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$match</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">status</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"completed"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$userId"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">totalSpent</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$items.price"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">orderCount</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">lastOrder</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$max</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$createdAt"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$lookup</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token keyword module" style="color:rgb(86, 156, 214)">from</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"customers"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">localField</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"_id"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">foreignField</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"userId"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token keyword module" style="color:rgb(86, 156, 214)">as</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"profile"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$unwind</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$profile"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$profile.name"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">email</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"$profile.email"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">totalSpent</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">orderCount</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token literal-property property">lastOrder</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">totalSpent</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">-</span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">$limit</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">25</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="index-to-support-your-pipeline">Index to Support Your Pipeline<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#index-to-support-your-pipeline" class="hash-link" aria-label="Direct link to Index to Support Your Pipeline" title="Direct link to Index to Support Your Pipeline">​</a></h3>
<p>Aggregation pipelines perform best when the <code>$match</code> stage can use an index. Create a compound index that covers the filter:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token property-access">orders</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">createIndex</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">status</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token literal-property property">createdAt</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">-</span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>For time-series workloads, a TTL index keeps your collection clean automatically:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token property-access">sessions</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">createIndex</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">createdAt</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property">expireAfterSeconds</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">86400</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="oplog-based-point-in-time-recovery">Oplog-Based Point-in-Time Recovery<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#oplog-based-point-in-time-recovery" class="hash-link" aria-label="Direct link to Oplog-Based Point-in-Time Recovery" title="Direct link to Oplog-Based Point-in-Time Recovery">​</a></h2>
<p>Every MongoDB service on FoundryDB gets continuous oplog archiving. The agent tails the <code>local.oplog.rs</code> collection every 5 seconds, batches entries into compressed slices every 10 minutes, encrypts each slice with AES-256-GCM, and uploads to object storage. This runs alongside daily <code>mongodump</code> full backups (with <code>--oplog</code> for consistency).</p>
<p>The PITR window covers 7 days. To check what is available:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/pitr-range</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"pitr_enabled"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"earliest_recovery_time"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-03-30T02:00:00Z"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"latest_recovery_time"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"2026-04-06T11:45:00Z"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"retention_days"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">7</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"archive_status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"active"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="restore-workflow">Restore Workflow<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#restore-workflow" class="hash-link" aria-label="Direct link to Restore Workflow" title="Direct link to Restore Workflow">​</a></h3>
<p>Imagine someone runs <code>db.orders.drop()</code> at 14:25 UTC. You can restore to 14:24:59, one second before the accident:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/backups/restore </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "restore_point": "2026-04-06T14:24:59Z",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "target_service_name": "analytics-mongo-restored",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "se-sto1"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 restore creates a <strong>new service</strong>. It never overwrites the source. FoundryDB finds the most recent full backup before your target time, restores it, then replays the archived oplog slices up to the exact timestamp. Monitor progress:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">restored_service_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Restore typically completes in 5 to 30 minutes depending on data size. Once the restored service reaches <code>running</code> status, verify your data, then update your application's connection string or delete the old service.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="wiredtiger-cache-tuning">WiredTiger Cache Tuning<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#wiredtiger-cache-tuning" class="hash-link" aria-label="Direct link to WiredTiger Cache Tuning" title="Direct link to WiredTiger Cache Tuning">​</a></h2>
<p>MongoDB uses WiredTiger as its storage engine. By default, FoundryDB configures a 1 GB WiredTiger cache, but you can tune it based on your workload. The <code>wiredTigerCacheSizeGB</code> parameter accepts values from 0.25 GB upward and does not require a restart.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PATCH </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/configuration </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "parameters": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "wiredTigerCacheSizeGB": "2.5"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Other tunable WiredTiger parameters:</p>
<table><thead><tr><th>Parameter</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><code>wiredTigerCacheSizeGB</code></td><td>1</td><td>Cache size in GB</td></tr><tr><td><code>wiredTigerConcurrentReadTransactions</code></td><td>128</td><td>Max concurrent read tickets (5-128)</td></tr><tr><td><code>wiredTigerConcurrentWriteTransactions</code></td><td>128</td><td>Max concurrent write tickets (5-128)</td></tr></tbody></table>
<p>Monitor WiredTiger cache pressure through the metrics API:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"https://api.foundrydb.com/managed-services/{id}/metrics?metric=wiredtiger_cache_used&amp;period=1h"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>If cache utilization consistently exceeds 80%, either increase <code>wiredTigerCacheSizeGB</code> or scale your compute plan to a higher tier.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-your-mongodb-service">Monitoring Your MongoDB Service<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#monitoring-your-mongodb-service" class="hash-link" aria-label="Direct link to Monitoring Your MongoDB Service" title="Direct link to Monitoring Your MongoDB Service">​</a></h2>
<p>FoundryDB collects MongoDB-specific metrics including connection counts, operation counters (inserts, queries, updates, deletes), replication lag, oplog window size, memory usage, and WiredTiger cache statistics. Enable slow operation profiling to catch inefficient queries:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> </span><span class="token variable" style="color:rgb(156, 220, 254)">$API_KEY</span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">:</span><span class="token variable" style="color:rgb(156, 220, 254)">$API_SECRET</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PATCH </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/configuration </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "parameters": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "operationProfiling.mode": "slowOp",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "operationProfiling.slowOpThresholdMs": "50"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="what-you-get-without-lifting-a-finger">What You Get Without Lifting a Finger<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#what-you-get-without-lifting-a-finger" class="hash-link" aria-label="Direct link to What You Get Without Lifting a Finger" title="Direct link to What You Get Without Lifting a Finger">​</a></h2>
<p>Every MongoDB service on FoundryDB includes:</p>
<ul>
<li><strong>3-member replica set</strong> with automatic failover (approximately 10 seconds)</li>
<li><strong>TLS required</strong> on all connections</li>
<li><strong>Daily automated backups</strong> via <code>mongodump --oplog</code></li>
<li><strong>Continuous oplog archiving</strong> (every 10 minutes, encrypted with AES-256-GCM)</li>
<li><strong>7-day PITR window</strong> for second-level recovery</li>
<li><strong>WiredTiger tuning</strong> without restarts</li>
<li><strong>EU data sovereignty</strong> with 5 European zones</li>
</ul>
<p>MongoDB versions 6, 7, and 8 are all available. Version 8 is recommended for new services.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://docs.foundrydb.com/blog/mongodb-aggregation-pipelines-pitr#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<p>Provision a MongoDB service in under five minutes. Read the <a href="https://docs.foundrydb.com/databases/mongodb" target="_blank" rel="noopener noreferrer">MongoDB documentation</a> for connection strings, configuration options, and failover details. Or try it now at <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">foundrydb.com</a>.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="mongodb" term="mongodb"/>
        <category label="aggregation" term="aggregation"/>
        <category label="pitr" term="pitr"/>
        <category label="replica-set" term="replica-set"/>
        <category label="oplog" term="oplog"/>
        <category label="wiredtiger" term="wiredtiger"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Full-Text Search with Managed OpenSearch: From Zero to Production]]></title>
        <id>https://docs.foundrydb.com/blog/opensearch-full-text-search-guide</id>
        <link href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Deploy managed OpenSearch on FoundryDB and build production search. Covers index design, analyzers, relevance tuning, aggregations, and OpenSearch Dashboards.]]></summary>
        <content type="html"><![CDATA[<p>Every application eventually outgrows <code>LIKE '%query%'</code>. Once your product catalog, help center, or log pipeline crosses a few million documents, you need an inverted index, not a sequential scan. OpenSearch provides exactly that: full-text search with relevance scoring, custom analyzers, aggregations, and a visualization layer built in.</p>
<p>The hard part is running it. JVM heap tuning, cluster formation, TLS certificate management, shard rebalancing, and snapshot configuration turn a "quick search feature" into a permanent ops project. FoundryDB removes all of that. You get a managed OpenSearch 2.19 cluster with TLS, authentication, automated snapshots, and monitoring out of the box.</p>
<p>This guide walks through deploying OpenSearch on FoundryDB and building production-quality search: from provisioning to index design, full-text queries, custom analyzers, and aggregations.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="provision-opensearch-in-under-five-minutes">Provision OpenSearch in Under Five Minutes<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#provision-opensearch-in-under-five-minutes" class="hash-link" aria-label="Direct link to Provision OpenSearch in Under Five Minutes" title="Direct link to Provision OpenSearch in Under Five Minutes">​</a></h2>
<p>Create a managed OpenSearch service with a single API call. FoundryDB handles JVM configuration (heap is automatically set to 50% of available memory, capped at 31 GB for compressed oops), the security plugin, TLS certificates, and systemd service management.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> YOUR_API_KEY: </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST https://api.foundrydb.com/managed-services </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "name": "product-search",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "database_type": "opensearch",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "version": "2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "plan_name": "tier-4",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "zone": "se-sto1",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_size_gb": 100,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_tier": "maxiops"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Within minutes, your service is live at <code>product-search.db.foundrydb.com:9200</code> with HTTPS and HTTP Basic authentication. Retrieve your credentials from the dashboard or the API:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> YOUR_API_KEY: </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/database-users</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Verify the cluster is healthy:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS https://product-search.db.foundrydb.com:9200/_cluster/health</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 should see <code>"status": "green"</code> and <code>"number_of_nodes": 1</code>. When you need more capacity, add data nodes through the API without downtime.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="design-your-index">Design Your Index<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#design-your-index" class="hash-link" aria-label="Direct link to Design Your Index" title="Direct link to Design Your Index">​</a></h2>
<p>Good search starts with good mappings. Define field types explicitly rather than relying on dynamic mapping, which often guesses wrong (mapping a product SKU as <code>text</code> when it should be <code>keyword</code>, for example).</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PUT </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://product-search.db.foundrydb.com:9200/products </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "settings": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "number_of_shards": 3,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "number_of_replicas": 1,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "index.refresh_interval": "1s",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "analysis": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "analyzer": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "product_analyzer": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">            "type": "custom",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">            "tokenizer": "standard",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">            "filter": ["lowercase", "asciifolding", "edge_ngram_filter"]</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        },</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "filter": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "edge_ngram_filter": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">            "type": "edge_ngram",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">            "min_gram": 2,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">            "max_gram": 15</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    },</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "mappings": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "properties": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "name":        {"type": "text", "analyzer": "product_analyzer",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">                        "search_analyzer": "standard"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "description": {"type": "text"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "category":    {"type": "keyword"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "price":       {"type": "float"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "tags":        {"type": "keyword"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "created_at":  {"type": "date"}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>A few things to note about this mapping:</p>
<ul>
<li><strong><code>text</code> vs <code>keyword</code></strong>: Use <code>text</code> for fields that need full-text search (tokenized, analyzed). Use <code>keyword</code> for exact matches, filters, and aggregations.</li>
<li><strong>Custom analyzer</strong>: The <code>product_analyzer</code> applies lowercasing, ASCII folding (so "cafe" matches "café"), and edge n-grams for autocomplete/prefix matching. We use <code>standard</code> as the search analyzer to avoid n-gram expansion at query time.</li>
<li><strong>Shard count</strong>: Three shards works well for indexes up to a few hundred gigabytes. FoundryDB's default limits allow up to 1000 fields per index and a 1-second refresh interval, both configurable.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="index-documents">Index Documents<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#index-documents" class="hash-link" aria-label="Direct link to Index Documents" title="Direct link to Index Documents">​</a></h2>
<p>Bulk indexing is significantly faster than single-document inserts. Use the <code>_bulk</code> API for any batch larger than a handful of documents:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://product-search.db.foundrydb.com:9200/products/_bulk </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/x-ndjson"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">{"index": {}}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">{"name": "Wireless Ergonomic Keyboard", "description": "Bluetooth mechanical keyboard with split layout and adjustable tenting", "category": "peripherals", "price": 149.99, "tags": ["keyboard", "ergonomic", "bluetooth"], "created_at": "2026-03-15"}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">{"index": {}}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">{"name": "USB-C Docking Station Pro", "description": "Triple display dock with 100W passthrough charging and 2.5GbE ethernet", "category": "peripherals", "price": 229.00, "tags": ["dock", "usb-c", "displays"], "created_at": "2026-03-20"}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">{"index": {}}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">{"name": "Noise Cancelling Headphones", "description": "Over-ear wireless headphones with adaptive ANC and 40-hour battery", "category": "audio", "price": 349.99, "tags": ["headphones", "anc", "wireless"], "created_at": "2026-04-01"}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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_LWe7" id="full-text-search-queries">Full-Text Search Queries<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#full-text-search-queries" class="hash-link" aria-label="Direct link to Full-Text Search Queries" title="Direct link to Full-Text Search Queries">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="simple-match">Simple Match<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#simple-match" class="hash-link" aria-label="Direct link to Simple Match" title="Direct link to Simple Match">​</a></h3>
<p>The <code>match</code> query tokenizes your search term and finds documents containing any of the tokens:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> GET </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://product-search.db.foundrydb.com:9200/products/_search </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"query": {"match": {"name": "wireless keyboard"}}}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This returns both the keyboard and the headphones, since both contain "wireless". Each result includes a <code>_score</code> reflecting how well it matches.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="multi-field-search">Multi-Field Search<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#multi-field-search" class="hash-link" aria-label="Direct link to Multi-Field Search" title="Direct link to Multi-Field Search">​</a></h3>
<p>Search across multiple fields at once, with optional field boosting:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> GET </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://product-search.db.foundrydb.com:9200/products/_search </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "query": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "multi_match": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "query": "ergonomic bluetooth",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "fields": ["name^3", "description", "tags^2"],</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "type": "best_fields"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>^3</code> on <code>name</code> means a match in the product name scores three times higher than a match in the description. This is the fastest way to tune relevance without reindexing.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="boolean-queries-for-filtering-and-faceting">Boolean Queries for Filtering and Faceting<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#boolean-queries-for-filtering-and-faceting" class="hash-link" aria-label="Direct link to Boolean Queries for Filtering and Faceting" title="Direct link to Boolean Queries for Filtering and Faceting">​</a></h3>
<p>Combine full-text search with structured filters using <code>bool</code> queries. Filters in the <code>filter</code> clause skip scoring (faster) and are cached:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> GET </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://product-search.db.foundrydb.com:9200/products/_search </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "query": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "bool": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "must": [</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          {"multi_match": {"query": "wireless", "fields": ["name^2", "description"]}}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        ],</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "filter": [</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          {"term": {"category": "peripherals"}},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          {"range": {"price": {"lte": 200}}}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        ]</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This finds "wireless" products in the "peripherals" category priced at 200 or less. Only the keyboard matches.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="aggregations-for-analytics">Aggregations for Analytics<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#aggregations-for-analytics" class="hash-link" aria-label="Direct link to Aggregations for Analytics" title="Direct link to Aggregations for Analytics">​</a></h2>
<p>OpenSearch aggregations turn your search index into an analytics engine. Combine them with queries to build faceted navigation or dashboards.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> GET </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://product-search.db.foundrydb.com:9200/products/_search </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "size": 0,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "aggs": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "by_category": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "terms": {"field": "category"},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "aggs": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "avg_price": {"avg": {"field": "price"}},</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "price_range": {"stats": {"field": "price"}}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      },</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "popular_tags": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "terms": {"field": "tags", "size": 10}</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Setting <code>"size": 0</code> returns only aggregation results, no document hits. This pattern powers category filters ("Peripherals (2)"), price range sliders, and tag clouds in search UIs.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monitor-cluster-health">Monitor Cluster Health<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#monitor-cluster-health" class="hash-link" aria-label="Direct link to Monitor Cluster Health" title="Direct link to Monitor Cluster Health">​</a></h2>
<p>FoundryDB exposes key OpenSearch metrics through its monitoring API: <code>cluster_health</code>, <code>active_shards</code>, <code>indexing_rate</code>, <code>search_rate</code>, <code>jvm_heap_used</code>, and <code>fielddata_evictions</code>. Export these to Datadog, Prometheus, Grafana Cloud, or any of the seven supported destinations.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> YOUR_API_KEY: </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"https://api.foundrydb.com/managed-services/{id}/metrics?metric=search_rate&amp;period=1h"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Watch <code>jvm_heap_used</code> and <code>fielddata_evictions</code> closely. If heap pressure stays above 75% or fielddata evictions spike, it is time to either scale up (bigger plan) or scale out (add data nodes). Both operations are a single API call with no downtime.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="index-lifecycle-management">Index Lifecycle Management<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#index-lifecycle-management" class="hash-link" aria-label="Direct link to Index Lifecycle Management" title="Direct link to Index Lifecycle Management">​</a></h2>
<p>Production search indexes grow indefinitely without governance. Use OpenSearch's ISM (Index State Management) policies to automate rollover and cleanup:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:YOUR_PASS </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PUT </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://product-search.db.foundrydb.com:9200/_plugins/_ism/policies/logs-policy </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "policy": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "description": "Roll over daily, delete after 30 days",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "states": [</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "name": "hot",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "actions": [{"rollover": {"min_size": "30gb", "min_index_age": "1d"}}],</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "transitions": [{"state_name": "delete", "conditions": {"min_index_age": "30d"}}]</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        },</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "name": "delete",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "actions": [{"delete": {}}],</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">          "transitions": []</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      ]</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This is especially useful for log analytics and event data where you want hot storage for recent data and automatic cleanup for older indexes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="scaling-your-cluster">Scaling Your Cluster<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#scaling-your-cluster" class="hash-link" aria-label="Direct link to Scaling Your Cluster" title="Direct link to Scaling Your Cluster">​</a></h2>
<p>When a single node is not enough, add data nodes to distribute shards and increase throughput:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> YOUR_API_KEY: </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"role": "data"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>FoundryDB handles cluster discovery, transport TLS between nodes, and shard rebalancing automatically. New nodes join the cluster using seed-based discovery, and the security plugin's shared CA ensures mutual TLS on the transport layer (port 9300) without manual certificate distribution.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-to-build-next">What to Build Next<a href="https://docs.foundrydb.com/blog/opensearch-full-text-search-guide#what-to-build-next" class="hash-link" aria-label="Direct link to What to Build Next" title="Direct link to What to Build Next">​</a></h2>
<p>OpenSearch on FoundryDB covers more than product search. Common patterns include:</p>
<ul>
<li><strong>Log analytics</strong>: Ship application logs via Filebeat or Fluent Bit, use ISM for retention, and query with aggregations for dashboards.</li>
<li><strong>Event analytics pipeline</strong>: Pair with managed Kafka for real-time ingestion. See the <a href="https://docs.foundrydb.com/docs/tutorials/build-event-analytics">Event Analytics tutorial</a> for a complete walkthrough.</li>
<li><strong>Autocomplete</strong>: The edge n-gram analyzer shown above powers type-ahead search with sub-50ms latency on most plans.</li>
<li><strong>Geospatial search</strong>: Use <code>geo_point</code> and <code>geo_shape</code> field types for location-based queries.</li>
</ul>
<p>Ready to add search to your stack? <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">Create a free FoundryDB account</a> and provision OpenSearch in under five minutes. Check the <a href="https://docs.foundrydb.com/databases/opensearch" target="_blank" rel="noopener noreferrer">OpenSearch documentation</a> for connection examples in Python, Node.js, and curl, or explore the <a href="https://docs.foundrydb.com/api" target="_blank" rel="noopener noreferrer">full API reference</a>.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="opensearch" term="opensearch"/>
        <category label="search" term="search"/>
        <category label="full-text" term="full-text"/>
        <category label="elasticsearch" term="elasticsearch"/>
        <category label="analytics" term="analytics"/>
        <category label="dashboards" term="dashboards"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Scaling Reads with PostgreSQL Read Replicas on FoundryDB]]></title>
        <id>https://docs.foundrydb.com/blog/postgresql-read-replicas-guide</id>
        <link href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Step-by-step guide to adding read replicas to your PostgreSQL service, routing queries with PgBouncer, and monitoring replication lag.]]></summary>
        <content type="html"><![CDATA[<p>Most PostgreSQL workloads are read-heavy. Dashboards, reporting queries, search, and API endpoints that serve cached-but-still-queried data all put pressure on a single primary. Vertical scaling helps, but at some point you are paying for CPU that only writes use while reads compete for the same connections.</p>
<p>Read replicas solve this by giving you additional PostgreSQL nodes that serve read queries from a continuously updated copy of your data. On FoundryDB, adding a replica takes one API call and a few minutes of provisioning time.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="when-you-need-read-replicas">When You Need Read Replicas<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#when-you-need-read-replicas" class="hash-link" aria-label="Direct link to When You Need Read Replicas" title="Direct link to When You Need Read Replicas">​</a></h2>
<p>A single-node PostgreSQL service handles a surprising amount of traffic. But three patterns signal that it is time to add replicas:</p>
<ul>
<li><strong>Read-heavy APIs.</strong> Your application runs 10x more SELECTs than INSERTs/UPDATEs. The primary spends most of its CPU serving reads instead of processing writes.</li>
<li><strong>Analytics and reporting.</strong> Long-running aggregation queries compete with transactional queries for connections and buffer cache. Running analytics on a replica keeps the primary fast.</li>
<li><strong>Geographic distribution.</strong> Replicas in different zones reduce read latency for users closer to those regions.</li>
</ul>
<p>A good rule of thumb: if your primary CPU is consistently above 70% and most of the load comes from SELECT queries, read replicas will help more than scaling up compute.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="adding-a-replica">Adding a Replica<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#adding-a-replica" class="hash-link" aria-label="Direct link to Adding a Replica" title="Direct link to Adding a Replica">​</a></h2>
<p>Add a replica to an existing PostgreSQL service with a single request:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"role": "replica"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Or use the CLI:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token plain">fdb services add-replica </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--service</span><span class="token plain"> my-postgres </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--zone</span><span class="token plain"> eu-helsinki</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>FoundryDB provisions a new VM, streams the current data from the primary using <code>pg_basebackup</code>, and starts streaming replication. For a 50 GB database on maxiops storage, this typically completes in under 5 minutes.</p>
<p>Once the replica is ready, list your nodes to get the replica's hostname:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"nodes"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"node_abc"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"primary"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"hostname"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"my-postgres-primary.db.foundrydb.com"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"running"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"node_def"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"replica"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"hostname"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"my-postgres-replica-1.db.foundrydb.com"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">      </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"running"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Each replica gets its own DNS hostname. You can connect to it directly for read queries using the same credentials and TLS settings as the primary.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-streaming-replication-works">How Streaming Replication Works<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#how-streaming-replication-works" class="hash-link" aria-label="Direct link to How Streaming Replication Works" title="Direct link to How Streaming Replication Works">​</a></h2>
<p>PostgreSQL streaming replication ships WAL (Write-Ahead Log) records from the primary to each replica in near-real-time. Every change (INSERT, UPDATE, DELETE, DDL) is first written to WAL on the primary, then streamed over a persistent TCP connection to the replica, which replays the changes against its own data files.</p>
<p>By default, FoundryDB uses <strong>asynchronous replication</strong>. The primary does not wait for replicas to confirm receipt before committing a transaction. This means writes are never slowed down by replica count, but there is a small window (typically under 10 milliseconds) where a replica may be slightly behind.</p>
<p>For workloads that require zero-lag reads (financial reporting, audit trails), you can switch to <strong>synchronous replication</strong> via the configuration API. This guarantees that at least one replica has received and flushed every committed transaction, at the cost of higher write latency.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PATCH </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/configuration </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"parameters": {"synchronous_commit": "remote_write"}}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Most applications should stay with asynchronous replication. The sub-second lag is invisible to end users.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="connection-routing-with-pgbouncer">Connection Routing with PgBouncer<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#connection-routing-with-pgbouncer" class="hash-link" aria-label="Direct link to Connection Routing with PgBouncer" title="Direct link to Connection Routing with PgBouncer">​</a></h2>
<p>Adding replicas only helps if your application actually sends reads to them. There are two approaches: application-level routing and connection pooling with PgBouncer.</p>
<p><strong>Application-level routing</strong> is the simplest. Use the primary hostname for writes and the replica hostname for reads in your application code:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">import</span><span class="token plain"> psycopg</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Write connection (primary)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">write_conn </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> psycopg</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">connect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"host=my-postgres-primary.db.foundrydb.com dbname=defaultdb sslmode=verify-full"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    user</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"app_user"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> password</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"secret"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Read connection (replica)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">read_conn </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> psycopg</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">connect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token string" style="color:rgb(206, 145, 120)">"host=my-postgres-replica-1.db.foundrydb.com dbname=defaultdb sslmode=verify-full"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">    user</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"app_user"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> password</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token string" style="color:rgb(206, 145, 120)">"secret"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>PgBouncer</strong> adds connection pooling on top. Enable it on your service to reduce connection overhead, especially when you have many short-lived application instances:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/pooler </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{"pool_size": 25, "pool_mode": "transaction"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>PgBouncer runs on port <code>5433</code> on each node (primary and replicas). In transaction mode, connections are returned to the pool after each transaction completes, allowing 25 server-side connections to serve hundreds of application connections.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-replication-lag">Monitoring Replication Lag<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#monitoring-replication-lag" class="hash-link" aria-label="Direct link to Monitoring Replication Lag" title="Direct link to Monitoring Replication Lag">​</a></h2>
<p>Replication lag is the most important metric for a replicated setup. It tells you how far behind a replica is relative to the primary.</p>
<p>Check lag for a specific node via the API:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">node_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/replication-status</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"replica"</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"lag_bytes"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1024</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"lag_seconds"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">0.002</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"connected"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token property">"sync_state"</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"streaming"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>For continuous monitoring, query the <code>pg_replication_lag_seconds</code> metric:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token string" style="color:rgb(206, 145, 120)">"https://api.foundrydb.com/managed-services/{id}/metrics?metric=pg_replication_lag_seconds&amp;period=1h"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>Set an alert to catch lag spikes before they affect your application:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/alerts/rules </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "metric": "replication_lag_seconds",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "condition": "gt",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "threshold": 30,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "severity": "warning",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "notification_channel_id": "channel_abc"</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>A threshold of 30 seconds is reasonable for most workloads. If your application requires stronger consistency guarantees on reads, tighten this to 5 or 10 seconds.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="failover-what-happens-when-the-primary-goes-down">Failover: What Happens When the Primary Goes Down<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#failover-what-happens-when-the-primary-goes-down" class="hash-link" aria-label="Direct link to Failover: What Happens When the Primary Goes Down" title="Direct link to Failover: What Happens When the Primary Goes Down">​</a></h2>
<p>With at least one replica, automatic failover is enabled. If the primary becomes unreachable, the system:</p>
<ol>
<li><strong>Detects the failure</strong> within approximately 30 seconds.</li>
<li><strong>Promotes the replica</strong> with the lowest replication lag to primary.</li>
<li><strong>Updates DNS</strong> so the primary hostname points to the new primary.</li>
<li><strong>Demotes the old primary</strong> to replica status once it recovers.</li>
</ol>
<p>Your application reconnects through DNS with no code changes needed. Design your connection logic with retry behavior (most PostgreSQL drivers handle this by default) and you will see only a brief interruption during the switchover.</p>
<p>You can also trigger a <strong>manual failover</strong> for planned maintenance:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> POST </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">replica_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/failover</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This performs a clean promotion with zero data loss, since the replica is fully caught up before the switch happens.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="removing-replicas">Removing Replicas<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#removing-replicas" class="hash-link" aria-label="Direct link to Removing Replicas" title="Direct link to Removing Replicas">​</a></h2>
<p>Scale down when the extra capacity is no longer needed:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> admin:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> DELETE </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/nodes/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">node_id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 replica VM is deprovisioned and the node is removed from the service. If you remove your last replica, automatic failover is disabled, so keep at least one replica for any production service.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="https://docs.foundrydb.com/blog/postgresql-read-replicas-guide#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary">​</a></h2>
<table><thead><tr><th>Setup</th><th>Nodes</th><th>Failover</th><th>Best for</th></tr></thead><tbody><tr><td>Single node</td><td>1</td><td>None</td><td>Development, staging</td></tr><tr><td>Primary + 1 replica</td><td>2</td><td>Automatic</td><td>Production minimum</td></tr><tr><td>Primary + 2 replicas</td><td>3</td><td>Automatic, read scaling</td><td>High-traffic production</td></tr></tbody></table>
<p>Read replicas give you horizontal read scaling, automatic failover, and analytics isolation without changing your application's write path. Start with one replica for failover protection, add more as your read traffic grows.</p>
<p>Read the full <a href="https://docs.foundrydb.com/databases/postgresql">PostgreSQL documentation</a> for extensions, configuration tuning, and point-in-time recovery. The <a href="https://docs.foundrydb.com/operations/high-availability">High Availability guide</a> covers failover behavior across all supported database engines.</p>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="postgresql" term="postgresql"/>
        <category label="read-replicas" term="read-replicas"/>
        <category label="scaling" term="scaling"/>
        <category label="pgbouncer" term="pgbouncer"/>
        <category label="replication" term="replication"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Predictive Autoscaling: Scale Your Database Before Demand Spikes]]></title>
        <id>https://docs.foundrydb.com/blog/predictive-autoscaling-databases</id>
        <link href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[FoundryDB's autoscaling analyzes usage patterns and scales compute and storage automatically. Configure policies, set cost limits, and let the platform handle capacity.]]></summary>
        <content type="html"><![CDATA[<p>Reactive autoscaling has a fundamental problem: it waits for something to go wrong. Your database hits 95% CPU, the autoscaler wakes up, requests a resize, and for the next few minutes your application eats latency while the new resources come online. If your traffic is predictable (and most production traffic is), this delay is avoidable.</p>
<p>FoundryDB's predictive autoscaling engine learns your workload's seasonal patterns and scales your database <em>before</em> demand spikes arrive. It combines real-time metric thresholds with historical baselines, anomaly detection, and configurable cost limits so you stay fast without overspending.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-works">How It Works<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#how-it-works" class="hash-link" aria-label="Direct link to How It Works" title="Direct link to How It Works">​</a></h2>
<p>The autoscaling system operates at two levels: a <strong>reactive policy</strong> that you configure per service via the API, and a <strong>predictive engine</strong> that runs continuously across all services.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="reactive-autoscale-policies">Reactive Autoscale Policies<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#reactive-autoscale-policies" class="hash-link" aria-label="Direct link to Reactive Autoscale Policies" title="Direct link to Reactive Autoscale Policies">​</a></h3>
<p>Every FoundryDB service supports a metric-based autoscale policy. You define which metrics to watch, what thresholds trigger a scale-up or scale-down, and the boundaries the autoscaler must stay within.</p>
<p>The four supported metrics are:</p>
<table><thead><tr><th>Metric</th><th>What it tracks</th></tr></thead><tbody><tr><td><code>cpu_percent</code></td><td>CPU utilization across the primary node</td></tr><tr><td><code>memory_percent</code></td><td>Memory pressure from buffers, caches, and active queries</td></tr><tr><td><code>connections_percent</code></td><td>Percentage of max connections in use</td></tr><tr><td><code>disk_percent</code></td><td>Storage utilization on the data volume</td></tr></tbody></table>
<p>Each metric has an independent <code>threshold_up</code> (trigger scale-up), <code>threshold_down</code> (trigger scale-down), and <code>duration_seconds</code> (how long the metric must sustain that level before acting). This prevents transient spikes from causing unnecessary tier changes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="predictive-engine">Predictive Engine<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#predictive-engine" class="hash-link" aria-label="Direct link to Predictive Engine" title="Direct link to Predictive Engine">​</a></h3>
<p>The predictive layer builds a <strong>seasonal baseline</strong> from your workload history. It looks at the same hour of the same day of the week over the past 7 days to compute a mean and standard deviation for CPU utilization. When current CPU deviates significantly from this baseline (measured by z-score), the engine acts preemptively rather than waiting for a hard threshold breach.</p>
<p>Three triggers drive predictive decisions:</p>
<ul>
<li><strong>Anomaly spike.</strong> A z-score above 2.5 combined with CPU already above 75% triggers an aggressive scale-up of 2 tiers. This handles sudden, unexpected load that the seasonal model didn't predict.</li>
<li><strong>Sustained growth.</strong> Three consecutive metric windows (each 15 minutes) all above the scale-up threshold triggers a 1-tier increase. This catches gradual load increases like organic traffic growth.</li>
<li><strong>Sustained low.</strong> Seven consecutive windows all below 30% CPU triggers a 1-tier decrease. The higher bar for scale-down (7 vs 3 windows) prevents premature downsizing during temporary lulls.</li>
</ul>
<p>Every decision (including no-ops) is recorded to an audit table for debugging, reporting, and cooldown enforcement.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="configuring-an-autoscale-policy">Configuring an Autoscale Policy<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#configuring-an-autoscale-policy" class="hash-link" aria-label="Direct link to Configuring an Autoscale Policy" title="Direct link to Configuring an Autoscale Policy">​</a></h2>
<p>Set up a CPU-based autoscale policy using the REST API:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PUT </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/autoscale-policy </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "enabled": true,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "metrics": [</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "metric": "cpu_percent",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "threshold_up": 80,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "threshold_down": 30,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "duration_seconds": 300</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      },</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "metric": "memory_percent",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "threshold_up": 85,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "threshold_down": 40,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">        "duration_seconds": 300</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    ],</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "min_plan": "tier-2",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "max_plan": "tier-8",</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "cooldown_seconds": 300</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>This tells the autoscaler: scale up when CPU exceeds 80% for 5 minutes, scale down when it stays below 30% for 5 minutes, and never go below <code>tier-2</code> (2 vCPU, 4 GB) or above <code>tier-8</code> (8 vCPU, 16 GB). After any scaling action, wait at least 5 minutes before making another decision.</p>
<p>The <code>min_plan</code> and <code>max_plan</code> boundaries are your cost controls. Setting <code>max_plan</code> to <code>tier-8</code> means your bill will never exceed the hourly rate for that tier, regardless of what the autoscaler recommends.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="storage-autoscaling">Storage Autoscaling<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#storage-autoscaling" class="hash-link" aria-label="Direct link to Storage Autoscaling" title="Direct link to Storage Autoscaling">​</a></h2>
<p>Storage autoscaling works independently from compute autoscaling. Unlike compute, storage can only grow (you cannot shrink a disk without risking data loss). Configure it alongside your compute policy:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> PUT </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/autoscale-policy </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'{</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "enabled": true,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    "storage_auto_scale": {</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "enabled": true,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "threshold_percent": 85,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "increment_gb": 50,</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">      "max_size_gb": 1000</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">    }</span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token string" style="color:rgb(206, 145, 120)">  }'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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>When disk usage crosses 85%, the autoscaler adds 50 GB. It repeats as needed until the disk reaches the 1000 GB cap. The storage autoscaler checks every 5 minutes, with a 60-minute cooldown between expansions.</p>
<p>Default values if you enable storage autoscaling without specifying parameters:</p>
<table><thead><tr><th>Parameter</th><th>Default</th></tr></thead><tbody><tr><td><code>threshold_percent</code></td><td>80%</td></tr><tr><td><code>increment_gb</code></td><td>10 GB</td></tr><tr><td><code>max_size_gb</code></td><td>500 GB</td></tr><tr><td><code>cooldown_minutes</code></td><td>60</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="scaling-history-and-audit-trail">Scaling History and Audit Trail<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#scaling-history-and-audit-trail" class="hash-link" aria-label="Direct link to Scaling History and Audit Trail" title="Direct link to Scaling History and Audit Trail">​</a></h2>
<p>Every scaling operation records who triggered it: <code>user</code> (manual), <code>auto_scale</code> (reactive policy), or <code>system</code> (predictive engine). You can query your service's scaling history to see what happened, when, and why:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/autoscale-policy</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response includes <code>last_scale_at</code> so you can see when the most recent action occurred. The predictive engine also maintains a separate audit table that logs the z-score, seasonal baseline, current CPU average, and confidence level for every decision, including decisions where it evaluated your service and chose not to scale.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="reactive-vs-predictive-when-each-fires">Reactive vs. Predictive: When Each Fires<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#reactive-vs-predictive-when-each-fires" class="hash-link" aria-label="Direct link to Reactive vs. Predictive: When Each Fires" title="Direct link to Reactive vs. Predictive: When Each Fires">​</a></h2>
<p>The two systems complement each other. Here is how they divide responsibility:</p>
<table><thead><tr><th>Scenario</th><th>Reactive</th><th>Predictive</th></tr></thead><tbody><tr><td>Monday morning traffic ramp-up</td><td>Fires after CPU crosses 80%</td><td>Fires before, based on last Monday's pattern</td></tr><tr><td>Unexpected viral traffic spike</td><td>Fires after 5 min sustained threshold</td><td>Fires immediately via anomaly detection (z-score &gt; 2.5)</td></tr><tr><td>Gradual organic growth over weeks</td><td>Fires when thresholds breach</td><td>Fires on sustained growth (3 consecutive high windows)</td></tr><tr><td>Weekend low traffic</td><td>Scales down after 5 min below threshold</td><td>Scales down after 7 consecutive low windows (~105 min)</td></tr><tr><td>One-off batch job spike</td><td>May fire if sustained &gt; <code>duration_seconds</code></td><td>Ignores if within seasonal norms</td></tr></tbody></table>
<p>The predictive engine is deliberately conservative. It requires a z-score above 2.5 for anomaly spikes (roughly 99th percentile deviation), 3 sustained high windows for growth, and 7 sustained low windows for scale-down. A 6-hour cooldown prevents thrashing from rapid successive decisions.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="dry-run-mode">Dry-Run Mode<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#dry-run-mode" class="hash-link" aria-label="Direct link to Dry-Run Mode" title="Direct link to Dry-Run Mode">​</a></h2>
<p>Before trusting the autoscaler with production changes, enable dry-run mode. In this mode, the predictive engine evaluates your workload and records all decisions to the audit log, but does not execute any tier changes. Review the decisions over a few days to verify the engine's judgment before going live.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="disabling-autoscaling">Disabling Autoscaling<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#disabling-autoscaling" class="hash-link" aria-label="Direct link to Disabling Autoscaling" title="Direct link to Disabling Autoscaling">​</a></h2>
<p>Remove the autoscale policy entirely:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#9CDCFE"><span class="token function" style="color:rgb(220, 220, 170)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-u</span><span class="token plain"> user:password </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-X</span><span class="token plain"> DELETE </span><span class="token punctuation" style="color:rgb(212, 212, 212)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#9CDCFE"><span class="token plain">  https://api.foundrydb.com/managed-services/</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain">/autoscale-policy</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><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_LjdS"><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 response confirms the timestamp when autoscaling was disabled. All existing resources remain at their current tier and size.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="best-practices">Best Practices<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#best-practices" class="hash-link" aria-label="Direct link to Best Practices" title="Direct link to Best Practices">​</a></h2>
<p><strong>Start with reactive, then layer predictive.</strong> Set conservative thresholds (80% up, 30% down) and monitor scaling events for a week. Once you trust the behavior, the predictive engine adds the look-ahead advantage.</p>
<p><strong>Set meaningful plan boundaries.</strong> Your <code>min_plan</code> should be the smallest tier that handles your baseline traffic. Your <code>max_plan</code> should be the largest tier your budget allows. The gap between them is the autoscaler's operating range.</p>
<p><strong>Use duration to filter noise.</strong> A <code>duration_seconds</code> of 300 (5 minutes) prevents one-off query spikes from triggering a resize. Reduce it to 60 only if your application is genuinely latency-sensitive to brief spikes.</p>
<p><strong>Monitor storage thresholds proactively.</strong> Unlike compute, storage cannot scale down. Set <code>max_size_gb</code> to a value you are comfortable paying for indefinitely, and monitor disk growth trends in your metrics dashboard.</p>
<p><strong>Review the audit log.</strong> The predictive scaling decisions table records every evaluation. If the engine is making decisions you disagree with, adjust the <code>min_plan</code>/<code>max_plan</code> boundaries or the reactive thresholds.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-next">What's Next<a href="https://docs.foundrydb.com/blog/predictive-autoscaling-databases#whats-next" class="hash-link" aria-label="Direct link to What's Next" title="Direct link to What's Next">​</a></h2>
<ul>
<li>Read the <a href="https://docs.foundrydb.com/operations/scaling" target="_blank" rel="noopener noreferrer">Scaling operations guide</a> for manual vertical and horizontal scaling</li>
<li>Explore <a href="https://docs.foundrydb.com/operations/monitoring" target="_blank" rel="noopener noreferrer">monitoring and metrics</a> to see the data that drives autoscaling decisions</li>
<li>Try <a href="https://foundrydb.com/" target="_blank" rel="noopener noreferrer">FoundryDB free</a> and set up your first autoscale policy in under 5 minutes</li>
</ul>]]></content>
        <author>
            <name>FoundryDB Team</name>
            <uri>https://foundrydb.com</uri>
        </author>
        <category label="autoscaling" term="autoscaling"/>
        <category label="scaling" term="scaling"/>
        <category label="performance" term="performance"/>
        <category label="cost-optimization" term="cost-optimization"/>
        <category label="monitoring" term="monitoring"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
</feed>