<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>TeaQL Blog</title>
        <link>https://teaql.io/blog</link>
        <description>TeaQL Blog</description>
        <lastBuildDate>Sun, 20 Sep 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[A Stable Rust Tool Facade for Humans and AI: 52 Utilities, Explicit Intent]]></title>
            <link>https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent</link>
            <guid>https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent</guid>
            <pubDate>Sun, 20 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Why TeaQL Tool puts 52 common Rust utilities behind one predictable facade—and uses types to require intent before context-bound results or side effects are used.]]></description>
            <content:encoded><![CDATA[<p>Rust does not have a shortage of good crates.</p>
<p>There is <code>uuid</code> for identifiers, <code>chrono</code> for time, <code>rust_decimal</code> for exact
decimal arithmetic, <code>serde_json</code> for JSON, and <code>reqwest</code> for HTTP. The challenge
in application development is often not finding a capability. It is keeping a
team fluent in many unrelated APIs while preventing infrastructure details from
spreading through business code.</p>
<p>AI coding makes that problem more visible. A model may understand the operation
we want while mixing together method names from another language, another
version, or another crate. The generated code looks plausible, but the API does
not exist.</p>
<p><a href="https://github.com/teaql/teaql-rust-utils" target="_blank" rel="noopener noreferrer" class="">TeaQL Tool</a> is our attempt to make
that surface smaller and more predictable. It places 52 common utilities behind
one <code>T::xxx()</code> facade, separates lightweight and dependency-heavy features, and
adds an optional context layer that requires code to state why a value is being
read, calculated, or changed.</p>
<p>It is partly inspired by libraries such as Hutool, but the interesting question
is not how many helpers we can collect. It is whether a stable, narrow API can
serve both application developers and coding agents without hiding Rust's
underlying ecosystem.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-problem-is-api-variance-not-missing-capability">The problem is API variance, not missing capability<a href="https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent#the-problem-is-api-variance-not-missing-capability" class="hash-link" aria-label="Direct link to The problem is API variance, not missing capability" title="Direct link to The problem is API variance, not missing capability" translate="no">​</a></h2>
<p>A typical service quickly needs identifiers, timestamps, money, JSON, regular
expressions, encoding, files, hashing, and HTTP. Using each underlying crate
directly is entirely reasonable, especially when an application needs its full
feature set.</p>
<p>For repeated business operations, however, every dependency introduces another
construction pattern, error model, naming convention, and upgrade path. The
business layer gradually learns more infrastructure than business semantics.
An AI agent has an even larger API space in which to guess.</p>
<p>TeaQL Tool does not reimplement the ecosystem. It provides a small facade over
selected, mature crates:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">teaql_tool</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">id</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">uuid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> now </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">json</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">r#"{"name":"TeaQL"}"#</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> digest </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">hash</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sha256</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">b"hello"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The caller starts at <code>T</code>, chooses a semantically named tool, and uses a compact
operation set. The facade can evolve its implementation without requiring every
call site to know which crate performs the work.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-the-52-tools-are-divided">How the 52 tools are divided<a href="https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent#how-the-52-tools-are-divided" class="hash-link" aria-label="Direct link to How the 52 tools are divided" title="Direct link to How the 52 tools are divided" translate="no">​</a></h2>
<p>The workspace contains five crates:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">teaql-tool-core</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       ├── teaql-tool-std       26 standard tools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       ├── teaql-tool-extra     26 extension tools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       └── teaql-tool           unified T:: facade</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    └── teaql-tool-context</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                        UserContext and intent adapters</span><br></div></code></pre></div></div>
<p><code>teaql-tool-std</code> contains 26 general-purpose tools: text, time, date ranges,
IDs, money, decimals, JSON, regex, encoding, hashes, files, lists, maps,
validation, masking, emoji, networking, colors, units, trees, and related
operations.</p>
<p><code>teaql-tool-extra</code> contains 26 tools with heavier dependencies or more explicit
IO: HTTP, commands, archives, Excel, CSV, images, email, JWT, encryption,
barcodes, QR codes, templates, an embedded key-value store, caching, a static
file server, a reverse proxy, cron scheduling, and file watching.</p>
<p><code>teaql-tool</code> is intentionally thin. It owns the public facade and feature
selection. The default <code>minimal</code> feature enables the standard tools; applications
opt into <code>extra</code> when they need the heavier integrations.</p>
<p>Until the crates are published independently, the facade can be used from the
Git repository:</p>
<div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">[dependencies]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">teaql-tool = {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    git = "https://github.com/teaql/teaql-rust-utils",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    features = ["std", "extra"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>The <a href="https://github.com/teaql/teaql-rust-utils#%EF%B8%8F-feature-inventory" target="_blank" rel="noopener noreferrer" class="">project README</a>
contains the complete inventory and the current context coverage.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-use-a-facade-in-rust">Why use a facade in Rust?<a href="https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent#why-use-a-facade-in-rust" class="hash-link" aria-label="Direct link to Why use a facade in Rust?" title="Direct link to Why use a facade in Rust?" translate="no">​</a></h2>
<p>A facade has a straightforward benefit: discoverability.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> tomorrow </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add_days</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> encoded </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">codec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">base64_encode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">b"Hello"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> masked </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">desensitize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">chinese_phone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"13812345678"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Developers and agents can search one namespace instead of rediscovering a
dependency for every common operation. Naming can remain consistent across
categories, and an underlying dependency upgrade does not automatically become
an application-wide migration.</p>
<p>The same abstraction has a cost. A facade exposes a deliberately smaller API
than its dependencies. If an application needs detailed <code>reqwest</code> connection
pool control, the complete <code>chrono</code> type system, or advanced image encoding
parameters, it should use those crates directly. TeaQL Tool is a business
convenience layer, not a replacement for the Rust ecosystem.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="put-the-reason-for-an-operation-in-the-type-flow">Put the reason for an operation in the type flow<a href="https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent#put-the-reason-for-an-operation-in-the-type-flow" class="hash-link" aria-label="Direct link to Put the reason for an operation in the type flow" title="Direct link to Put the reason for an operation in the type flow" translate="no">​</a></h2>
<p>A predictable method name reduces API guessing. It does not explain why
application code is reading a file, obtaining the current time, or starting a
command.</p>
<p><code>teaql-tool-context</code> explores a second idea: context-bound tools return wrappers
that require the caller to add intent before extracting a value or executing a
side effect.</p>
<p>The API distinguishes three meanings:</p>
<ul>
<li class=""><code>comment(...)</code> explains a calculation;</li>
<li class=""><code>purpose(...)</code> explains a read;</li>
<li class=""><code>audit_as(...)</code> describes and executes a side effect.</li>
</ul>
<p>For example:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">teaql_tool_context</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">prelude</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> now </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"read the current time for the payment policy"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> deadline </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">time</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add_days</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">now</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">7</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"calculate the payment grace period"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">file</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">write_string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"deadline.txt"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> deadline</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to_rfc3339</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">audit_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"export the calculated payment deadline"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Calculation and read wrappers keep their inner values private. Code that needs
the value must explicitly consume the wrapper through the matching intent
method.</p>
<p>Side effects need a stronger boundary. <code>MustAuditAs&lt;T&gt;</code> stores a deferred action
rather than an already-computed result:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">MustAuditAs</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    action</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Box</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">dyn</span><span class="token plain"> </span><span class="token class-name">FnOnce</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Send</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token lifetime-annotation symbol" style="color:#36acaa">'static</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">impl</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">MustAuditAs</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">audit_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> description</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">impl</span><span class="token plain"> </span><span class="token class-name">Into</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> action </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">action</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">take</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"action executes once"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">action</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">description</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">into</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>If a caller drops this value without calling <code>.audit_as(...)</code>, the deferred file
write, command, or email is not performed. Tests cover both paths: execution
after an audit description and no execution after the pending action is dropped.</p>
<p>These wrappers enforce that intent is supplied at the API boundary. How that
description enters structured logs, traces, or an audit store remains an
application-runtime integration concern. Separating those responsibilities
keeps the type-level contract honest: collect intent first, route it through the
appropriate runtime policy second.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-a-smaller-api-helps-coding-agents">Why a smaller API helps coding agents<a href="https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent#why-a-smaller-api-helps-coding-agents" class="hash-link" aria-label="Direct link to Why a smaller API helps coding agents" title="Direct link to Why a smaller API helps coding agents" translate="no">​</a></h2>
<p>An LLM can know that a capability exists while still confusing its crate,
version, or exact method name. A facade narrows that generation space:</p>
<ul>
<li class="">entry points follow <code>T::xxx()</code> or <code>ctx.xxx()</code>;</li>
<li class="">related capabilities use a consistent naming style;</li>
<li class="">underlying dependency changes need not propagate into business code;</li>
<li class="">wrapper types let the compiler identify missing intent;</li>
<li class="">project rules can disallow bypassing context-bound IO in application code.</li>
</ul>
<p>This does not eliminate hallucinations. It changes the problem from guessing
among many third-party APIs to selecting from a finite, project-owned surface,
then lets the Rust compiler verify the result.</p>
<p>For us, this is part of a broader harness-engineering principle: if a coding
rule matters repeatedly, move as much of it as possible from prompt prose into
an executable interface.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="current-boundaries">Current boundaries<a href="https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent#current-boundaries" class="hash-link" aria-label="Direct link to Current boundaries" title="Direct link to Current boundaries" translate="no">​</a></h2>
<p>TeaQL Tool is an early project, and several boundaries are intentional or still
in progress:</p>
<ol>
<li class="">The facade covers frequent operations, not every capability of every wrapped
crate.</li>
<li class="">Enabling <code>extra</code> adds networking, image, spreadsheet, SMTP, and server
dependencies; compile time and binary size should be measured rather than
ignored.</li>
<li class="">Stable facade names create a compatibility responsibility for maintainers.</li>
<li class="">The context layer currently covers all 26 standard tools, 21 extension tools,
and a separate asynchronous HTTP adapter. Cron, proxy, server, and watcher
adapters remain to be added.</li>
<li class="">Intent wrappers are an enforcement boundary, but full audit-sink integration
is still runtime-specific work.</li>
</ol>
<p>The next steps are compatibility and compile-fail tests, feature-level build
measurements, remaining context adapters, and deeper TeaQL runtime audit and
trace integration.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-question-for-the-rust-community">A question for the Rust community<a href="https://teaql.io/blog/rust-tool-facade-52-utilities-explicit-intent#a-question-for-the-rust-community" class="hash-link" aria-label="Direct link to A question for the Rust community" title="Direct link to A question for the Rust community" translate="no">​</a></h2>
<p>Rust's crate ecosystem is strongest when applications can use focused libraries
directly. At the same time, business systems and coding agents benefit from
small, stable, project-owned interfaces.</p>
<p>Where should that boundary sit?</p>
<p>Does a Hutool-style facade reduce accidental complexity in a Rust application,
or does it hide crate boundaries that should remain explicit? For AI-generated
code, is a stable, constrained API more valuable than direct access to every
underlying capability?</p>
<p>TeaQL Tool is open source, and we would value concrete criticism of both the
tool selection and the intent-wrapper design:</p>
<p><a href="https://github.com/teaql/teaql-rust-utils" target="_blank" rel="noopener noreferrer" class="">github.com/teaql/teaql-rust-utils</a></p>]]></content:encoded>
            <category>teaql</category>
            <category>rust</category>
            <category>ai-coding</category>
            <category>tools</category>
            <category>api-design</category>
            <category>developer-experience</category>
        </item>
        <item>
            <title><![CDATA[TeaQL Was 2,000× Faster Than the Obvious SQLx Query—Here’s What Actually Happened]]></title>
            <link>https://teaql.io/blog/teaql-2000x-obvious-sqlx-query</link>
            <guid>https://teaql.io/blog/teaql-2000x-obvious-sqlx-query</guid>
            <pubDate>Sun, 06 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A reproducible MusicBrainz benchmark shows a 2,378× gap between two SQLx execution plans—and why TeaQL can choose bounded work without leaving its governed query model.]]></description>
            <content:encoded><![CDATA[<p>We recently measured two implementations of the same application request over
the MusicBrainz dataset:</p>
<blockquote>
<p>Load the newest 100 recordings that have linked works, and load at most ten
work relations for each recording.</p>
</blockquote>
<p>The controlled SQLx test returned the same 100 recordings, 103 relation rows,
103 links, 103 link types, and Work-ID checksum through both paths. One took
5,871.169 milliseconds. The other took 2.469 milliseconds—a <strong>2,378×
difference inside SQLx itself</strong>.</p>
<p>TeaQL Rust previously completed the corresponding typed graph workload in
2.864 milliseconds. That does not mean TeaQL has a PostgreSQL driver 2,000×
faster than SQLx. The difference was the amount of work requested from the
database. The expert SQLx control proves it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-teaql-is">What TeaQL is<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#what-teaql-is" class="hash-link" aria-label="Direct link to What TeaQL is" title="Direct link to What TeaQL is" translate="no">​</a></h2>
<p>TeaQL is a model-driven application runtime. A semantic model generates
language-native Q APIs for queries, E APIs for loaded expressions, and governed
graph mutation APIs. The same model can target seven runtimes: Rust, Java,
TypeScript, Go, Swift, .NET, and Python.</p>
<p>Queries carry more than SQL structure. They retain relation bounds, loaded
state, tenant and authorization scope, version policy, and an operational
<code>comment</code> and <code>purpose</code>. That additional intent is what made this optimization
possible without turning application code into handcrafted SQL.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-obvious-single-statement-sqlx-solution">The obvious single-statement SQLx solution<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#the-obvious-single-statement-sqlx-solution" class="hash-link" aria-label="Direct link to The obvious single-statement SQLx solution" title="Direct link to The obvious single-statement SQLx solution" translate="no">​</a></h2>
<p>A capable SQL developer may reach for a window function to express Top-N per
parent:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">WITH</span><span class="token plain"> ranked </span><span class="token keyword" style="color:#00009f">AS</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> relation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         row_number</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">OVER</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">           </span><span class="token keyword" style="color:#00009f">PARTITION</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">BY</span><span class="token plain"> relation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">entity0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">           </span><span class="token keyword" style="color:#00009f">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">BY</span><span class="token plain"> relation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">link_order </span><span class="token keyword" style="color:#00009f">ASC</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> relation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token keyword" style="color:#00009f">DESC</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">AS</span><span class="token plain"> rn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> l_recording_work relation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> relation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">version </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> roots </span><span class="token keyword" style="color:#00009f">AS</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> recording</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> recording</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> recording</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">version </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">EXISTS</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> ranked </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> ranked</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">entity0 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> recording</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">BY</span><span class="token plain"> recording</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token keyword" style="color:#00009f">DESC</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">LIMIT</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> roots</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">LEFT</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">JOIN</span><span class="token plain"> ranked</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">ON</span><span class="token plain"> ranked</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">entity0 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> roots</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> ranked</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">rn </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">LEFT</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">JOIN</span><span class="token plain"> link </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">LEFT</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">JOIN</span><span class="token plain"> link_type </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">LEFT</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">JOIN</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">work</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>This is readable, set-oriented SQL. It is not an obviously careless query. It
also asks PostgreSQL to rank the complete relation population—about 2.7 million
rows in this fixture—before reducing the graph to 100 roots and 103 relations.</p>
<p>In the Rust SQLx control, the PostgreSQL median was 5,871.169 ms. An earlier
raw JDBC run measured 5,579.224 ms, confirming that changing the client library
does not remove the database work. DuckDB, whose vectorized analytical engine
fits this global-ranking shape better, completed the earlier query in
808.158 ms.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-business-request-carried-a-stronger-bound">The business request carried a stronger bound<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#the-business-request-carried-a-stronger-bound" class="hash-link" aria-label="Direct link to The business request carried a stronger bound" title="Direct link to The business request carried a stronger bound" translate="no">​</a></h2>
<p>The corresponding TeaQL request describes a bounded object graph. In an
application, we can name and reuse each meaningful graph fragment instead of
repeating the whole nested request at every call site:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">link_type_details</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">LinkTypeRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">link_types_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_description</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_phrase</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">link_details</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">LinkRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">links_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_ended</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_type_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">link_type_details</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">recording_work_details</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">LRecordingWorkRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">l_recording_works_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_order</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">link_details</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_entity1_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">works_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_link_order_asc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_id_desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">recordings_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_length</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">have_l_recording_works</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_l_recording_work_list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">recording_work_details</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_id_desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">100</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"what: load the MB03 recording-work graph"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"why: render bounded recording-work details"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute_for_list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The main request now reads as a composition of business-relevant graph
fragments. The helpers are ordinary typed Rust functions: they can be reused,
tested, extended, and combined like building blocks. They do not hide raw SQL
or switch to a second query system; each still returns a generated TeaQL query
selection that the runtime can govern as one request.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>See the same TeaQL request fully expanded</summary><div><div class="collapsibleContent_i85q"><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">recordings_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_length</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">have_l_recording_works</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_l_recording_work_list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">l_recording_works_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_order</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">links_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_ended</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_type_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">link_types_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_description</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_link_phrase</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_entity1_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">works_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_link_order_asc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_id_desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_id_desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">100</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"what: load the MB03 recording-work graph"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"why: render bounded recording-work details"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute_for_list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div></div></div></details>
<p>The important information is not the Rust syntax. It is the request shape:</p>
<ol>
<li class="">choose 100 matching roots;</li>
<li class="">load no more than ten ordered relations for each selected root;</li>
<li class="">hydrate only the referenced Link, LinkType, and Work objects;</li>
<li class="">preserve version, policy, comment, and purpose semantics throughout.</li>
</ol>
<p>TeaQL can select the roots first and constrain relation loading to those roots.
It does not need to rank relations belonging to recordings that cannot appear
on this page.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-sqlx-control-explains-the-result">The SQLx control explains the result<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#the-sqlx-control-explains-the-result" class="hash-link" aria-label="Direct link to The SQLx control explains the result" title="Direct link to The SQLx control explains the result" translate="no">​</a></h2>
<p>We then wrote the optimization explicitly in ordinary SQLx:</p>
<ol>
<li class="">fetch the 100 root recording IDs;</li>
<li class="">pass those IDs to a second parameterized query;</li>
<li class="">rank only relations whose <code>entity0</code> belongs to that root set;</li>
<li class="">join Link, LinkType, and Work for the bounded rows.</li>
</ol>
<p>Using one initialized SQLx pool connection, three warmups, and ten sequential
measurements, the medians were:</p>
<table><thead><tr><th>Implementation</th><th style="text-align:right">PostgreSQL median</th></tr></thead><tbody><tr><td>SQLx, natural global-window statement</td><td style="text-align:right">5,871.169 ms</td></tr><tr><td>SQLx, expert root-first two-stage plan</td><td style="text-align:right"><strong>2.469 ms</strong></td></tr><tr><td>TeaQL Rust, typed governed graph (separate retained run)</td><td style="text-align:right">2.864 ms</td></tr></tbody></table>
<p>The first two rows are the controlled 2,378× comparison. The TeaQL row comes
from a separate retained run and is context, not part of that ratio. It includes
generated typed requests, relation hydration, and identity-graph assembly; the
SQLx control decodes aggregate tuples.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-much-code-did-each-plan-require">How much code did each plan require?<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#how-much-code-did-each-plan-require" class="hash-link" aria-label="Direct link to How much code did each plan require?" title="Direct link to How much code did each plan require?" translate="no">​</a></h2>
<p>We counted the physical non-blank lines that declare and execute each query.
Imports, connection setup, timing, result gates, and reporting were excluded;
embedded SQL was included because the application owns it.</p>
<table><thead><tr><th>Implementation</th><th style="text-align:right">Query LOC</th></tr></thead><tbody><tr><td>SQLx, natural global window</td><td style="text-align:right">26</td></tr><tr><td>SQLx, expert root-first</td><td style="text-align:right">34</td></tr><tr><td>TeaQL, typed graph request (fully expanded)</td><td style="text-align:right">27</td></tr></tbody></table>
<p>The numbers are deliberately unexciting: TeaQL is not winning through a tiny
code-golf example. Its fully expanded typed request is about the same size as
the natural SQL. The composed version moves reusable graph fragments out of the
call site; it improves local readability without pretending that their
definitions vanished. The important difference is what those lines preserve.
The expert SQLx version owns two SQL statements, transfers root IDs, binds the
array, and must keep both stages semantically aligned. TeaQL declares the root
and relation bounds once inside the graph request.</p>
<p>LOC is formatting-sensitive, and the SQLx benchmark returns aggregate tuples
while TeaQL hydrates entities. It should be read as maintenance surface, not as
a universal productivity score. A fuller hand-written implementation would
also need typed SQLx rows, graph assembly, authorization, tenant isolation,
loaded-state handling, and observability.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="performance-is-only-half-of-the-problem">Performance is only half of the problem<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#performance-is-only-half-of-the-problem" class="hash-link" aria-label="Direct link to Performance is only half of the problem" title="Direct link to Performance is only half of the problem" translate="no">​</a></h2>
<p>An expert can—and in this benchmark did—write the fast SQLx plan. TeaQL's
advantage is not that manual optimization is impossible. It is that application
developers do not have to discover, implement, and repeatedly preserve it
themselves.</p>
<p>Every handcrafted optimization creates another enforcement point. The root
query may contain a tenant predicate while the child query accidentally omits
it. The same can happen to authorization scope, soft-delete/version policy,
privacy masking, or trace metadata. Such mistakes are especially easy when an
AI coding agent rewrites a query for performance: the output looks faster and
can still leak another tenant's children.</p>
<p>TeaQL keeps both stages inside the same governed execution model. This is part
of TeaQL Harness Engineering: reduce the space in which generated code can be
fast but semantically or operationally wrong.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-benchmark-provesand-what-it-does-not">What the benchmark proves—and what it does not<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#what-the-benchmark-provesand-what-it-does-not" class="hash-link" aria-label="Direct link to What the benchmark proves—and what it does not" title="Direct link to What the benchmark proves—and what it does not" translate="no">​</a></h2>
<p>It proves that API semantics can give a runtime enough information to avoid a
large amount of unnecessary database work. It also shows why query-count rules
are incomplete: one elegant statement can do much more work than several
bounded statements.</p>
<p>It does not prove that:</p>
<ul>
<li class="">TeaQL has an intrinsically faster PostgreSQL driver than SQLx;</li>
<li class="">every window query is slow;</li>
<li class="">multiple queries are always preferable;</li>
<li class="">these timings generalize to other hardware, datasets, indexes, or databases;</li>
<li class="">2,378× is a general TeaQL-versus-SQLx performance ratio.</li>
</ul>
<p>The controlled result is narrower and more useful:</p>
<blockquote>
<p>The obvious SQLx query ranked 2.7 million rows for a page containing 103
relations. Once the business bounds were applied before ranking, most of that
work disappeared.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="reproduce-it">Reproduce it<a href="https://teaql.io/blog/teaql-2000x-obvious-sqlx-query#reproduce-it" class="hash-link" aria-label="Direct link to Reproduce it" title="Direct link to Reproduce it" translate="no">​</a></h2>
<p>The public
<a href="https://github.com/teaql/teaql-runtime-benchmark" target="_blank" rel="noopener noreferrer" class="">TeaQL runtime benchmark repository</a>
retains four related evidence packages:</p>
<ol>
<li class=""><a href="https://github.com/teaql/teaql-runtime-benchmark/tree/main/benchmarks/B001-rust-orm-musicbrainz" target="_blank" rel="noopener noreferrer" class="">B001</a>: Rust TeaQL, Diesel, and SeaORM typed graph workloads;</li>
<li class=""><a href="https://github.com/teaql/teaql-runtime-benchmark/tree/main/benchmarks/B002-duckdb-musicbrainz-engine" target="_blank" rel="noopener noreferrer" class="">B002</a>: raw JDBC across PostgreSQL and DuckDB;</li>
<li class=""><a href="https://github.com/teaql/teaql-runtime-benchmark/tree/main/benchmarks/B003-java-teaql-musicbrainz" target="_blank" rel="noopener noreferrer" class="">B003</a>: Java TeaQL across PostgreSQL and DuckDB;</li>
<li class=""><a href="https://github.com/teaql/teaql-runtime-benchmark/tree/main/benchmarks/B004-rust-sqlx-musicbrainz" target="_blank" rel="noopener noreferrer" class="">B004</a>: natural and expert root-first SQLx plans with a correctness gate.</li>
</ol>
<p>Each package records source, query shape, environment, warmups, measurements,
cardinalities, and checksums. B004 also contains an executable LOC counter.</p>
<p>The 2,378× headline is therefore reproducible, but deliberately narrow. The
broader TeaQL claim is about making the good plan declarative, typed, reusable,
and governed.</p>]]></content:encoded>
            <category>teaql</category>
            <category>rust</category>
            <category>sqlx</category>
            <category>benchmark</category>
            <category>postgresql</category>
            <category>musicbrainz</category>
            <category>query-optimization</category>
            <category>harness-engineering</category>
        </item>
        <item>
            <title><![CDATA[Direct Data API or Governed Business Query API? Supabase and TeaQL Solve Different Boundaries]]></title>
            <link>https://teaql.io/blog/direct-data-api-vs-governed-business-query-api</link>
            <guid>https://teaql.io/blog/direct-data-api-vs-governed-business-query-api</guid>
            <pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Supabase gives applications a direct Data API. TeaQL gives applications and AI agents a governed business query API across Java, Rust, and other runtimes.]]></description>
            <content:encoded><![CDATA[<p>Supabase gives applications a direct Data API. TeaQL gives applications and
AI agents a governed business query API.</p>
<p>The two ideas can produce a similar developer experience: a frontend composes
a query instead of waiting for a backend team to add one more endpoint. But
they place the public boundary at different layers of the system.</p>
<p>Supabase reflects a PostgreSQL schema into an API. TeaQL exposes capabilities
from a shared business model and lets a trusted runtime decide how those
capabilities are executed. That difference becomes important when an
application has complex authorization, several backend languages, multiple
data sources, or AI agents that need composition without database authority.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="first-supabase-solves-a-real-problem-well">First, Supabase solves a real problem well<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#first-supabase-solves-a-real-problem-well" class="hash-link" aria-label="Direct link to First, Supabase solves a real problem well" title="Direct link to First, Supabase solves a real problem well" translate="no">​</a></h2>
<p>Supabase's official documentation describes its Data API as an API generated
directly from the database schema. It can be called from a browser, uses
PostgREST, and works with PostgreSQL grants and Row Level Security. Supabase
supports both a two-tier architecture, where the browser accesses the Data API,
and a three-tier architecture with an application server.</p>
<p>That is a compelling model for many products:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> supabase</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword module" style="color:#00009f">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'orders'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">select</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'id,status,total_amount'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">eq</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'status'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'NEW'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">order</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'id'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">ascending</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>The application gets a useful query surface quickly. PostgreSQL remains the
execution engine, while grants and RLS determine which objects and rows a role
may access. Supabase explicitly recommends RLS and least-privilege grants for
frontend access and warns that service-role credentials must never be exposed
in the browser.</p>
<p>Those are strengths, not shortcomings. TeaQL is not trying to reproduce a
PostgreSQL platform, authentication product, storage service, or hosted
backend. It starts from a different question:</p>
<blockquote>
<p>What should the query boundary look like when the public contract is the
business model rather than the database schema?</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="similar-experience-different-authority">Similar experience, different authority<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#similar-experience-different-authority" class="hash-link" aria-label="Direct link to Similar experience, different authority" title="Direct link to Similar experience, different authority" translate="no">​</a></h2>
<p>A TeaQL TypeScript application normally composes the query through the
model-generated <code>Q</code> API:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> orders</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> SmartList</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">CustomerOrder</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">Q</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">customerOrders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">withOrderNumberStartingWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'WEB-'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">withTotalAmountGreaterThanOrEqualTo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectOrderNumber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectTotalAmount</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orderByIdDescending</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'what: load high-value active orders'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'why: render the operations queue'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">executeForList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p><code>customerOrders</code>, <code>withOrderNumberStartingWith</code>, <code>selectTotalAmount</code>, and the
returned <code>CustomerOrder</code> are generated from the model. They are not strings
invented by the application. Rename or remove a modeled field and this code
stops compiling. Editor completion also exposes only the operations generated
for that field type.</p>
<p>The generated request builds TeaQL's internal typed query model. At a federal
boundary it is serialized into a canonical TeaQL Federal Protocol request; the
application does not need to construct that string-keyed wire envelope itself.
The browser transmits neither SQL nor a runtime-native object. The receiving
application maps the public entity and field vocabulary to capabilities that
its trusted policy permits.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">TypeScript query</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      ▼</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">TeaQL Federal Protocol</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      ▼</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">entity / field / operator / limit policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      ▼</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">tenant + actor + purpose context</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      ▼</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Java or Rust TeaQL runtime</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      ▼</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">configured data services</span><br></div></code></pre></div></div>
<p>The same TypeScript query can be executed by a Java backend or a Rust backend.
The backend may use PostgreSQL, SQLite, another supported provider, or a
composed data-service topology. The frontend contract does not become a raw
view of any one physical schema.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-business-model-is-not-just-a-nicer-table-name">A business model is not just a nicer table name<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#a-business-model-is-not-just-a-nicer-table-name" class="hash-link" aria-label="Direct link to A business model is not just a nicer table name" title="Direct link to A business model is not just a nicer table name" translate="no">​</a></h2>
<p>Database tables are an implementation model. A governed application needs
additional concepts:</p>
<ul>
<li class="">which entities and fields this caller may query;</li>
<li class="">which operators are allowed for each exposed field;</li>
<li class="">tenant and regional boundaries injected by the server;</li>
<li class="">required query limits and stable ordering;</li>
<li class="">loaded, null, and not-loaded object state;</li>
<li class="">comments describing what the query does;</li>
<li class="">purpose describing why it is being executed;</li>
<li class="">audit and telemetry that remain independent from business payloads;</li>
<li class="">consistent semantics when a service moves between runtime languages.</li>
</ul>
<p>Some of these rules can be implemented with PostgreSQL RLS, views, functions,
grants, and API-server code. TeaQL's proposition is not that they are impossible
elsewhere. It is that they should form one generated, testable runtime contract
rather than being reconstructed independently in every application layer.</p>
<p>This is especially relevant to AI agents. An agent can productively combine
approved predicates, projections, relations, and facets. It should not receive
the authority to invent SQL against an internal schema or to omit the tenant
condition because it did not appear in the prompt.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-model-generates-both-sides-only-the-trusted-side-owns-policy">One model generates both sides; only the trusted side owns policy<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#one-model-generates-both-sides-only-the-trusted-side-owns-policy" class="hash-link" aria-label="Direct link to One model generates both sides; only the trusted side owns policy" title="Direct link to One model generates both sides; only the trusted side owns policy" translate="no">​</a></h2>
<p>TeaQL starts with one KSML business model. From that model, the generator can
produce both sides of the interaction:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">                         one KSML model</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                               │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                ┌──────────────┴──────────────┐</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                ▼                             ▼</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       generated client API          generated server runtime</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       Q.customerOrders()             entities and metadata</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       typed predicates               query execution</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       typed projections              checker and fix lifecycle</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       typed result objects           mutation and audit lifecycle</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                │                             │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                │                    application customization</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                │                    tenant and actor policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                │                    workflow authorization</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                └──────── TFP ────────────────┘</span><br></div></code></pre></div></div>
<p>The client is intentionally close to the generated model. A frontend developer
normally consumes the generated <code>Q</code> API directly. The client does not need a
copy of the organization's authorization implementation, and it must not
receive server secrets or trusted policy state.</p>
<p>The server is generated from the same model but is designed to be customized.
An application installs its runtime module, checkers, fixes, behaviors, trusted
field mappings, and authorization rules there. The server may expose only a
subset of the generated model through TFP. It may also add tenant conditions or
reject an operation even when the client constructed a perfectly valid typed
query.</p>
<p>This separation is important: <strong>type-safe means structurally valid; it does not
mean authorized</strong>. Generated client code prevents accidental field and operator
mistakes. The trusted server decides whether this actor may perform this query
or mutation in the current business context.</p>
<p>Because both sides originate from the same model, they share entity, field,
relationship, nullability, and query semantics without sharing authority. The
client can remain mostly generated and immediately usable, while the server can
be deeply adapted to the organization.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tenant-isolation-is-only-the-beginning">Tenant isolation is only the beginning<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#tenant-isolation-is-only-the-beginning" class="hash-link" aria-label="Direct link to Tenant isolation is only the beginning" title="Direct link to Tenant isolation is only the beginning" translate="no">​</a></h2>
<p>Consider a procurement application used by many companies. Every contract
belongs to a tenant. A user from tenant A must never read or mutate a contract
from tenant B—even if a request explicitly supplies tenant B's identifier.</p>
<p>TeaQL treats the tenant as trusted context rather than ordinary client input:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">browser request: contracts over 1,000,000</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">authenticated context: tenant=A, actor=alice, roles=[buyer]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">effective server query:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  requested business predicates</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  AND tenant = context.tenant</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  AND fields/operators allowed by server policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  AND runtime execution limits</span><br></div></code></pre></div></div>
<p>The frontend can compose the useful part of the question, but it cannot remove
or replace the server-injected tenant boundary. The same rule applies whether
the query is executed by the Java runtime today or a Rust service after a later
migration.</p>
<p>Now add a common enterprise authorization rule:</p>
<blockquote>
<p>A contract up to 1,000,000 may follow the normal approval path. A contract
above 1,000,000 must be approved by a second authorized person, and the second
approver cannot be the person who submitted it.</p>
</blockquote>
<p>This is not merely “can this role update this row?” The decision depends on:</p>
<ul>
<li class="">the tenant of the contract and the actor;</li>
<li class="">the contract amount and currency;</li>
<li class="">the current workflow state;</li>
<li class="">the actor's approval authority;</li>
<li class="">prior mutation history;</li>
<li class="">separation of duties between submitter and approver;</li>
<li class="">possibly regional or legal-entity rules.</li>
</ul>
<p>In TeaQL, the generated mutation enters the server runtime with an authenticated
context. Server-side checker/behavior policy can reject the transition, or move
the contract into a <code>PENDING_SECOND_APPROVAL</code> state and record the decision in
the mutation and audit lifecycle. The client still uses the generated contract
API; it does not duplicate the threshold rule or decide that its own request is
authorized.</p>
<p>PostgreSQL and Supabase can implement sophisticated rules using RLS, grants,
views, triggers, database functions, or a custom application server. The point
is not that a million-unit approval is impossible there. The architectural
question is where that evolving business workflow lives. Once an application
needs value-dependent approval, separation of duties, audit reasons, several
services, and multiple runtime languages, a table-reflected API alone is no
longer the complete business boundary.</p>
<p>TeaQL keeps the public query composable while placing these decisions in a
model-aware server runtime. That is what “governed” adds to “direct.”</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="facets-show-why-this-boundary-matters">Facets show why this boundary matters<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#facets-show-why-this-boundary-matters" class="hash-link" aria-label="Direct link to Facets show why this boundary matters" title="Direct link to Facets show why this boundary matters" translate="no">​</a></h2>
<p>Suppose an order page needs both filtered orders and status counts. The client
can request a relation facet:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> statusValues </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">Q</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orderStatuses</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectLabel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">countAs</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'orderCount'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'what: load status facet values'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'why: render order filters'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> orders </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">Q</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">customerOrders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">withTotalAmountGreaterThanOrEqualTo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectOrderNumber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'what: load orders with their status facet'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'why: render the governed order list'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">facetByStatusAs</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'statusFacet'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> statusValues</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">executeForList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> statusFacet </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> orders</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">facet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'statusFacet'</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>The server retains the outer filter when calculating membership counts. It
validates the relation, nested fields, aggregate, page limit, comment, and
purpose. It can return every allowed status—including a zero-count value—or
only matched values according to the explicit option.</p>
<p>This is still composable frontend querying, but the expensive operation is not
defined solely by whatever expression arrives from the browser. Its shape is a
bounded protocol capability.</p>
<p>TeaQL currently retains executable conformance for this path with a TypeScript
client against both Java and Rust endpoints. The same fixture verifies the
result and negative policy cases instead of treating a successful HTTP response
as sufficient evidence.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-each-approach-fits">Where each approach fits<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#where-each-approach-fits" class="hash-link" aria-label="Direct link to Where each approach fits" title="Direct link to Where each approach fits" translate="no">​</a></h2>
<p>The useful comparison is not “which product has more features?” It is “where
should authority live for this application?”</p>
<table><thead><tr><th>Requirement</th><th>Direct Data API is attractive</th><th>Governed business query API is attractive</th></tr></thead><tbody><tr><td>Deliver CRUD over PostgreSQL quickly</td><td>Yes</td><td>Possible, but not its main differentiation</td></tr><tr><td>Browser queries closely follow tables/views</td><td>Yes</td><td>Usually intentionally abstracted</td></tr><tr><td>PostgreSQL RLS is the primary policy layer</td><td>Yes</td><td>Can coexist, but runtime policy is also explicit</td></tr><tr><td>Java and Rust services share one query contract</td><td>Requires an application-level design</td><td>A core TeaQL objective</td></tr><tr><td>Backend may migrate between languages</td><td>Public contract may need coordination</td><td>TFP keeps the client query stable</td></tr><tr><td>AI composes new business questions</td><td>Requires carefully designed tools and policy</td><td>The query model is designed as the governed tool boundary</td></tr><tr><td>Cross-data-source relations</td><td>Application-specific</td><td>Part of the runtime model</td></tr><tr><td>Query purpose and diagnostic comment are required</td><td>Application-specific</td><td>Part of the query contract</td></tr></tbody></table>
<p>For a small PostgreSQL application that wants a backend immediately, a direct
Data API may be exactly the right abstraction. For a domain with substantial
business policy, several runtimes, gradual Java-to-Rust migration, or agentic
query composition, binding the public query contract directly to storage can
become limiting.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-goal-is-not-unrestricted-frontend-querying">The goal is not unrestricted frontend querying<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#the-goal-is-not-unrestricted-frontend-querying" class="hash-link" aria-label="Direct link to The goal is not unrestricted frontend querying" title="Direct link to The goal is not unrestricted frontend querying" translate="no">​</a></h2>
<p>“Let the frontend query” can sound like moving backend authority into the
browser. That is not the TeaQL design.</p>
<p>The client controls composition only within a capability vocabulary. The
server owns identity, tenant scope, allowed entities, field mappings,
operators, limits, execution, and error classification. Unknown fields and
unsupported operators fail closed. Internal database errors and mappings do
not become the public protocol.</p>
<p>That produces a useful middle ground:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">fixed endpoints            governed composition                raw SQL</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">low flexibility   &lt;------------------------------------&gt;   high authority</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                         TeaQL aims here</span><br></div></code></pre></div></div>
<p>Applications and agents gain enough freedom to answer questions that were not
pre-packaged as dedicated endpoints. The backend keeps enough authority to
make those questions safe, explainable, portable, and testable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-sentence-to-remember">One sentence to remember<a href="https://teaql.io/blog/direct-data-api-vs-governed-business-query-api#one-sentence-to-remember" class="hash-link" aria-label="Direct link to One sentence to remember" title="Direct link to One sentence to remember" translate="no">​</a></h2>
<blockquote>
<p>Supabase gives applications a direct Data API. TeaQL gives applications and
AI agents a governed business query API.</p>
</blockquote>
<p>They address neighboring needs. The distinction is the layer being exposed:
the database as an API, or the governed business model as an API.</p>
<p>Further reading:</p>
<ul>
<li class=""><a href="https://supabase.com/docs/guides/api" target="_blank" rel="noopener noreferrer" class="">Supabase Data REST API</a></li>
<li class=""><a href="https://supabase.com/docs/guides/api/securing-your-api" target="_blank" rel="noopener noreferrer" class="">Supabase: securing the Data API</a></li>
<li class=""><a href="https://github.com/teaql" target="_blank" rel="noopener noreferrer" class="">TeaQL on GitHub</a></li>
</ul>]]></content:encoded>
            <category>teaql</category>
            <category>supabase</category>
            <category>query-language</category>
            <category>architecture</category>
            <category>governance</category>
            <category>ai</category>
            <category>agents</category>
            <category>typescript</category>
        </item>
        <item>
            <title><![CDATA[What Does a Governed Data Runtime Cost? TeaQL vs Diesel and SeaORM on MusicBrainz]]></title>
            <link>https://teaql.io/blog/musicbrainz-rust-orm-benchmark</link>
            <guid>https://teaql.io/blog/musicbrainz-rust-orm-benchmark</guid>
            <pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A correctness-gated PostgreSQL comparison of TeaQL, Diesel, and SeaORM across deep, wide, and generic MusicBrainz relationship graphs.]]></description>
            <content:encoded><![CDATA[<p>TeaQL does more during a query than map database rows into Rust structs.</p>
<p>It preserves loaded, null, and not-loaded state. It builds an identity-consistent
object graph. It carries query purpose and diagnostic comments. The same runtime
also supports checker/fix behavior, mutation ledgers, audit boundaries, and
cross-data-source relations.</p>
<p>That raises a fair question: what does this additional runtime model cost on a
real relational graph?</p>
<p>We tested a retained TeaQL Rust build against Diesel and SeaORM using a
PostgreSQL copy of the public
<a href="https://musicbrainz.org/doc/MusicBrainz_Database/Download" target="_blank" rel="noopener noreferrer" class="">MusicBrainz database</a>.
The result is more useful than a simple winner: across three relationship
shapes, TeaQL consistently landed between Diesel and SeaORM—and came within
3.4% of Diesel on one five-query graph.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-result-first">The result first<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#the-result-first" class="hash-link" aria-label="Direct link to The result first" title="Direct link to The result first" translate="no">​</a></h2>
<p>These are medians from the retained local run on August 25, 2026:</p>
<table><thead><tr><th>Workload</th><th style="text-align:right">Diesel</th><th style="text-align:right">TeaQL</th><th style="text-align:right">SeaORM</th><th>TeaQL relative position</th></tr></thead><tbody><tr><td>MB01: seven-level release graph</td><td style="text-align:right"><strong>2.325 ms</strong></td><td style="text-align:right">2.925 ms</td><td style="text-align:right">3.898 ms</td><td>25.8% slower than Diesel; 25.0% faster than SeaORM</td></tr><tr><td>MB02: wide artist-credit graph</td><td style="text-align:right"><strong>49.949 ms</strong></td><td style="text-align:right">57.587 ms</td><td style="text-align:right">64.560 ms</td><td>15.3% slower than Diesel; 10.8% faster than SeaORM</td></tr><tr><td>MB03: generic recording/work graph</td><td style="text-align:right"><strong>2.769 ms</strong></td><td style="text-align:right">2.864 ms</td><td style="text-align:right">3.932 ms</td><td>3.4% slower than Diesel; 27.2% faster than SeaORM</td></tr></tbody></table>
<p>Every framework passed the same cardinality and checksum gate before its timing
was accepted. A fast result with a missing relation, projection, active-version
predicate, or duplicate path was a failed run, not a benchmark result.</p>
<p>This is not evidence that TeaQL is universally faster than SeaORM, or that
Diesel is universally faster than TeaQL. It is evidence that TeaQL's generated,
identity-preserving relationship loading is competitive on these three graph
shapes while retaining a broader runtime contract.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="three-graph-shapes-not-one-convenient-query">Three graph shapes, not one convenient query<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#three-graph-shapes-not-one-convenient-query" class="hash-link" aria-label="Direct link to Three graph shapes, not one convenient query" title="Direct link to Three graph shapes, not one convenient query" translate="no">​</a></h2>
<p>A single benchmark can accidentally select the exact shape one implementation
optimizes best. We therefore retained three materially different reads.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mb01-a-deep-release-graph">MB01: a deep release graph<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#mb01-a-deep-release-graph" class="hash-link" aria-label="Direct link to MB01: a deep release graph" title="Direct link to MB01: a deep release graph" translate="no">​</a></h3>
<p>MB01 follows seven entity types:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Release</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Medium</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Track</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Recording</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; ArtistCredit</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; ArtistCreditName</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Artist</span><br></div></code></pre></div></div>
<p>Each operation returns:</p>
<ul>
<li class="">10 releases;</li>
<li class="">14 media;</li>
<li class="">133 tracks;</li>
<li class="">176 artist-credit-name path traversals;</li>
<li class="">176 artist traversals;</li>
<li class="">checksum <code>13,877,887,930</code>.</li>
</ul>
<p>All three implementations execute seven parameterized statements and project
the same IDs, versions, names, and foreign keys. This workload tests depth and
repeated identities more than raw row volume.</p>
<p>TeaQL's application query is assembled from generated, typed request pieces.
For example, the reusable lower half of the graph can be named once:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">artist_credit_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">ArtistCreditRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">artist_credits_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_artist_credit_name_list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">artist_credit_names_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_artist_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">artists_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">recording_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">RecordingRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">recordings_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_artist_credit_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">artist_credit_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">medium_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">MediumRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">mediums_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_track_list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">tracks_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_recording_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">recording_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">releases_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_medium_list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">medium_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_id_desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"what: repeatedly load the MB01 release graph"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"why: compare mainstream ORM graph loading"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute_for_list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The helper functions are ordinary typed request builders: they can be reused,
extended, or nested in another request without falling back to SQL strings or
an untyped include specification. This makes a large query read more like a set
of Lego pieces than one monolithic expression. <code>comment</code> and <code>purpose</code> remain
on the final execution boundary because they describe this concrete operation,
not a reusable projection fragment.</p>
<p>The composed request is expanded into one query per graph level. The runtime
installs the results into a flat identity graph and exposes typed relationships
without requiring application-owned lookup maps.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mb02-a-wide-collaboration-graph">MB02: a wide collaboration graph<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#mb02-a-wide-collaboration-graph" class="hash-link" aria-label="Direct link to MB02: a wide collaboration graph" title="Direct link to MB02: a wide collaboration graph" translate="no">​</a></h3>
<p>MB02 selects the 100 <code>ArtistCredit</code> rows with the largest <code>artist_count</code> above
one, loads their ordered <code>ArtistCreditName</code> members, and resolves every typed
<code>Artist</code>.</p>
<p>Each accepted operation returns:</p>
<ul>
<li class="">100 artist credits;</li>
<li class="">2,090 memberships;</li>
<li class="">2,090 resolved artists;</li>
<li class="">zero <code>artist_count</code> mismatches;</li>
<li class="">checksum <code>2,584,441,647</code>.</li>
</ul>
<p>This graph executes only three queries, but materializes 2,290
identity-bearing entities across 2,090 relation paths. Here TeaQL was 15.3%
behind Diesel and 10.8% ahead of SeaORM. The result suggests that TeaQL's graph
assembly scales reasonably as decoding and relationship volume dominate fixed
runtime costs.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mb03-a-small-generic-link-graph">MB03: a small generic link graph<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#mb03-a-small-generic-link-graph" class="hash-link" aria-label="Direct link to MB03: a small generic link graph" title="Direct link to MB03: a small generic link graph" translate="no">​</a></h3>
<p>MusicBrainz represents recording-to-work relationships through a generic link
model. MB03 selects 100 recent recordings that have work relations, loads up to
ten association rows per recording, and resolves both sides:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Recording</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; LRecordingWork</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       -&gt; Link -&gt; LinkType</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       -&gt; Work</span><br></div></code></pre></div></div>
<p>The accepted result contains 103 association rows, 103 links, 103 link types,
and 103 works. No parent exceeds the per-parent limit, and the checksum is
<code>6,601,766,716</code>.</p>
<p>This workload performs five database queries for only 512 total entities. It is
therefore sensitive to fixed query, repository, and graph-assembly costs. In
the retained run, TeaQL was only 3.4% behind Diesel and 27.2% ahead of SeaORM.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-mainstream-usage-means-here">What “mainstream usage” means here<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#what-mainstream-usage-means-here" class="hash-link" aria-label="Direct link to What “mainstream usage” means here" title="Direct link to What “mainstream usage” means here" translate="no">​</a></h2>
<p>We did not ask every framework to imitate TeaQL's internal strategy or race on
hand-written SQL.</p>
<ul>
<li class="">Diesel uses derived <code>Associations</code>, <code>belonging_to</code>, and <code>grouped_by</code>, plus
typed <code>eq_any</code> parent lookups where the traversal direction requires them.</li>
<li class="">SeaORM uses <code>LoaderTrait::load_many</code>, <code>LoaderTrait::load_one</code>, and its typed
query API.</li>
<li class="">TeaQL uses its generated Q API and nested <code>select_*_with</code> relation selection.</li>
</ul>
<p>No implementation uses raw SQL, stored procedures, custom PostgreSQL
functions, or a workload-specific result cache. A single join across the whole
graph was deliberately excluded because multiple to-many edges multiply rows
and do not represent a robust default loading strategy.</p>
<p>The database sees different parameterization details where each framework has
its own normal policy. TeaQL uses scalar equality for one ID, scalar <code>IN</code> for
small sets, and PostgreSQL <code>= ANY($1)</code> for larger sets. That stable array-bound
shape avoids expanded-parameter limits; it is not presented as proof of a
universal speed advantage.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="measurement-protocol">Measurement protocol<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#measurement-protocol" class="hash-link" aria-label="Direct link to Measurement protocol" title="Direct link to Measurement protocol" translate="no">​</a></h2>
<p>The retained comparison used:</p>
<ul>
<li class="">local PostgreSQL with the same MusicBrainz dataset for all frameworks;</li>
<li class="">Rust <code>--release</code> builds;</li>
<li class="">sequential operations with no client-side concurrency;</li>
<li class="">connection and runtime construction outside the measured interval;</li>
<li class="">three complete warm-up operations per framework process;</li>
<li class="">five framework-order-rotated rounds;</li>
<li class="">100 complete operations per MB01 result;</li>
<li class="">20 complete MB02 and MB03 operations per result;</li>
<li class="">SQL and process logging disabled for all measured frameworks;</li>
<li class="">full graph traversal and checksum validation in every process.</li>
</ul>
<p>We report medians because the machine showed material round-to-round variance.
Publishing extra decimal places would imply accuracy the experiment does not
have.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="reproducing-the-evidence-is-intentionally-simple">Reproducing the evidence is intentionally simple<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#reproducing-the-evidence-is-intentionally-simple" class="hash-link" aria-label="Direct link to Reproducing the evidence is intentionally simple" title="Direct link to Reproducing the evidence is intentionally simple" translate="no">​</a></h2>
<p>The complete B001 evidence package is public in
<a href="https://github.com/teaql/teaql-runtime-benchmark/tree/main/benchmarks/B001-rust-orm-musicbrainz" target="_blank" rel="noopener noreferrer" class="">teaql/teaql-runtime-benchmark</a>.
There are two useful levels of reproduction.</p>
<p>First, anyone can recalculate all nine published medians and verify the raw
logs, correctness gates, model, runner sources, schema augmentation, and every
file in the retained generated library with one command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">git clone https://github.com/teaql/teaql-runtime-benchmark.git</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">cd teaql-runtime-benchmark</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">benchmarks/B001-rust-orm-musicbrainz/scripts/verify.sh</span><br></div></code></pre></div></div>
<p>This audit needs no database and no Rust compiler. The same command runs in the
repository's GitHub Actions workflow.</p>
<p>Second, the exact 2026-08-01 MusicBrainz sample can be reconstructed with a
fixed snapshot URL, SHA-256, and pinned official loader commit:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">benchmarks/B001-rust-orm-musicbrainz/scripts/setup-dataset.sh</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">export MUSICBRAINZ_BENCHMARK_DATABASE_URL=\</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">'postgresql://musicbrainz:musicbrainz@127.0.0.1:55434/musicbrainz_teaql'</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">benchmarks/B001-rust-orm-musicbrainz/scripts/preflight.sh</span><br></div></code></pre></div></div>
<p>The setup downloads the public sample, verifies it, imports the official
schema, creates a separate TeaQL benchmark database, applies the idempotent
augmentation, and checks the fixture cardinalities. It requires Docker Compose,
about 4 GiB of RAM, and roughly 15 GiB of disk.</p>
<p>There is one important boundary. A 2026-09-02 audit found that the retained
generated library uses the older <code>EntityRoot</code> API and does not compile with the
runtime commit recorded as 4.2.25; the original runner lock file was also not
retained. We therefore classify this as <strong>historical evidence whose numbers are
auditable</strong>, not an exact source-and-latency replay. We do not silently switch
runtime versions to make the command green. A new evidence run will add the
fully locked end-to-end replay while preserving this historical result.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-more-teaql-workloads-without-an-orm-ranking">Two more TeaQL workloads, without an ORM ranking<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#two-more-teaql-workloads-without-an-orm-ranking" class="hash-link" aria-label="Direct link to Two more TeaQL workloads, without an ORM ranking" title="Direct link to Two more TeaQL workloads, without an ORM ranking" translate="no">​</a></h2>
<p>We also reran two exploratory TeaQL-only scenarios after moving reverse
relations out of generated entity storage:</p>
<table><thead><tr><th>Workload</th><th style="text-align:right">TeaQL median</th><th>Correctness gate</th></tr></thead><tbody><tr><td>MB04: 1,000 releases and release-country geography</td><td style="text-align:right">8.381 ms</td><td>1,035 availability rows, 42 distinct areas, zero missing targets</td></tr><tr><td>MB05: concurrent alias search across three entity types</td><td style="text-align:right">45.068 ms</td><td>204 resolved parents, zero missing targets</td></tr></tbody></table>
<p>We have not yet implemented equivalent mainstream Diesel and SeaORM versions
of MB04 and MB05. These numbers are useful runtime regression evidence, but
they are not a cross-framework comparison.</p>
<p>That distinction matters. A benchmark becomes less credible every time an
author quietly converts “not measured” into “probably faster.”</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-relations-moved-out-of-rust-entity-structs">Why relations moved out of Rust entity structs<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#why-relations-moved-out-of-rust-entity-structs" class="hash-link" aria-label="Direct link to Why relations moved out of Rust entity structs" title="Direct link to Why relations moved out of Rust entity structs" translate="no">​</a></h2>
<p>The relation-state design being evaluated changes how generated reverse
relations are represented. A parent
entity no longer embeds every reverse <code>SmartList&lt;Child&gt;</code> in its structure.
Instead, the runtime owns the loaded identity graph, and generated accessors
return a <code>RelationHandle</code> with three explicit states:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Loaded     the selected relationship contains values</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Empty      the relationship was selected and contains no values</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">NotLoaded  the relationship was not selected</span><br></div></code></pre></div></div>
<p>There is no implicit database access when an accessor is called.</p>
<p>This reduces generated type-graph growth and makes cyclic models easier for
Rust to compile and represent. It also keeps the public API compact: business
code still asks the entity for its typed relation, while the data lives in the
runtime identity graph.</p>
<p>The trade-off is measurable. Direct traversal through a relation handle is
slightly more expensive than reading an embedded list. In MB01, traversal was
roughly 0.144 ms in this run versus about 0.062 ms in an earlier retained
baseline. The absolute difference is small compared with database and hydration
time, but we report it because removing an embedded field is not literally
free.</p>
<p>Overall MB01–MB05 query performance did not regress as a group, and all
correctness gates remained stable. We do not attribute every improvement to
<code>RelationHandle</code>; the measured build also contains compact-row decoding,
prepared-statement caching, reduced metadata allocation, and flatter identity
hydration introduced during the same optimization period.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="performance-is-not-the-whole-runtime-contract">Performance is not the whole runtime contract<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#performance-is-not-the-whole-runtime-contract" class="hash-link" aria-label="Direct link to Performance is not the whole runtime contract" title="Direct link to Performance is not the whole runtime contract" translate="no">​</a></h2>
<p>Diesel is an excellent reference point for efficient, strongly typed Rust
database access. SeaORM provides a productive async ORM model with generated
entities and relationship loaders. TeaQL targets a different application
boundary: one governed domain model generates consistent APIs across Java,
Rust, TypeScript, Swift, Python, .NET, and Go.</p>
<p>The measured TeaQL query path additionally preserves:</p>
<ul>
<li class="">typed loaded/null/not-loaded semantics;</li>
<li class="">identity-consistent relationship graphs;</li>
<li class="">mandatory query purpose and diagnostic comments;</li>
<li class="">active-version filtering;</li>
<li class="">a shared contract with checker/fix, audit, and mutation APIs;</li>
<li class="">runtime-managed cross-data-source relationship capability.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-query-log-that-records-intent-not-only-sql">A query log that records intent, not only SQL<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#a-query-log-that-records-intent-not-only-sql" class="hash-link" aria-label="Direct link to A query log that records intent, not only SQL" title="Direct link to A query log that records intent, not only SQL" translate="no">​</a></h3>
<p>The two strings at the end of the benchmark request are not decorative:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"what: repeatedly load the MB01 release graph"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"why: compare mainstream ORM graph loading"</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>TeaQL carries both into query diagnostics. The SQL tells an operator what the
database executed; <code>comment</code> identifies the concrete operation, while <code>purpose</code>
records why the application asked for it. That distinction is useful when a
slow query, an unexpected access path, or AI-generated application code must be
reviewed after the fact. It also gives observability systems a stable piece of
business intent instead of asking an operator to reconstruct intent from a
prepared statement and a stack trace.</p>
<p>There is a small discipline cost: application queries must declare their
intent. We consider that a feature of a governed runtime, especially when more
code is produced or modified by AI agents.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-benchmark-is-part-of-a-harness-not-a-one-off-race">The benchmark is part of a harness, not a one-off race<a href="https://teaql.io/blog/musicbrainz-rust-orm-benchmark#the-benchmark-is-part-of-a-harness-not-a-one-off-race" class="hash-link" aria-label="Direct link to The benchmark is part of a harness, not a one-off race" title="Direct link to The benchmark is part of a harness, not a one-off race" translate="no">​</a></h3>
<p>TeaQL is developed with the
<a href="https://github.com/teaql/teaql-agent-kit" target="_blank" rel="noopener noreferrer" class="">TeaQL Agent Kit</a>, a Harness
Engineering workflow that gives coding agents model rules, generated Assist
material, executable checks, and retained evidence. The goal is not merely to
make an agent produce a query that compiles once. The harness repeatedly checks
whether model evaluation, generation, runtime behavior, and documentation still
agree as the system evolves.</p>
<p>The same domain model and API concepts are maintained across seven generated
runtime families: Java, Rust, TypeScript, Swift, Python, .NET, and Go. Each
language keeps its native naming and type-system conventions, while TeaQL's Q,
E, mutation, checker/fix, audit, loaded-state, and Assist vocabulary provide a
shared conceptual contract. Conformance evidence matters here: “seven
languages” is an engineering obligation to detect and close gaps, not a claim
that every implementation already has identical maturity or performance.</p>
<p>Not every one of those capabilities is exercised by these read-only queries,
so the benchmark cannot assign a precise cost to each feature. They explain why
our goal is not to turn TeaQL into a thin SQL tuple decoder. The engineering
target is to keep the governed runtime close enough to the fastest mainstream
typed approach that teams do not have to abandon the higher-level contract for
ordinary application queries.</p>
<p>On this MusicBrainz sample, that target is credible: TeaQL is not the fastest in
the table, but it is consistently competitive—and the gap is small enough to
measure rather than hand-wave. The value proposition is therefore not “the
fastest Rust query at any cost.” It is competitive query performance together
with explainable intent, a continuously exercised AI coding harness, and one
domain contract that can travel across seven languages.</p>
<p>TeaQL Rust is available at
<a href="https://github.com/teaql/teaql-rs" target="_blank" rel="noopener noreferrer" class="">github.com/teaql/teaql-rs</a>. The benchmark
article and its follow-up evidence are tracked publicly in
<a href="https://github.com/teaql/teaql-io-site/issues/13" target="_blank" rel="noopener noreferrer" class="">teaql-io-site issue #13</a>.</p>
<hr>
<p><strong>Authorship disclosure:</strong> This article was written by Philip Zhang with
LLM-assisted drafting and editing. The benchmark design, execution, validation,
and conclusions were reviewed by the author.</p>]]></content:encoded>
            <category>teaql</category>
            <category>rust</category>
            <category>benchmark</category>
            <category>postgresql</category>
            <category>musicbrainz</category>
            <category>diesel</category>
            <category>seaorm</category>
            <category>orm</category>
        </item>
        <item>
            <title><![CDATA[Rust Made Object Mutation Hard—So We Designed It Properly]]></title>
            <link>https://teaql.io/blog/rust-made-object-mutation-explicit</link>
            <guid>https://teaql.io/blog/rust-made-object-mutation-explicit</guid>
            <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How Rust ownership pressure led TeaQL to an explicit graph-wide mutation ledger—and a clearer mutation contract shared by seven runtimes.]]></description>
            <content:encoded><![CDATA[<p>Object mutation feels simple in many languages. Load an object, call a setter,
and save it. If the object has children, mutate those too. Somewhere underneath,
an ORM compares snapshots, observes setters, or walks an identity map and turns
the differences into database commands.</p>
<p>Then we implemented the same programming model in Rust.</p>
<p>Rust did not let us casually hide shared mutable state behind an object graph.
Ownership and borrowing forced us to answer questions that our other runtimes
had allowed us to postpone.</p>
<ul>
<li class="">Who owns the pending changes?</li>
<li class="">What is the mutation boundary when a parent and its children change together?</li>
<li class="">How does a save operation discover a change made through another reference?</li>
<li class="">Where is the original version kept for optimistic locking?</li>
<li class="">What happens to pending changes when validation or persistence fails?</li>
</ul>
<p>Our first reaction was that Rust made an otherwise ordinary API unnecessarily
difficult. The more useful conclusion was the opposite: the ordinary API had
been relying on behavior that was never clearly designed.</p>
<p>The answer became a mutation ledger shared by an object graph. It began as a
way to make Rust mutation practical. It ended up becoming the mutation model for
all seven TeaQL runtimes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-hidden-contract-behind-a-setter">The Hidden Contract Behind a Setter<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#the-hidden-contract-behind-a-setter" class="hash-link" aria-label="Direct link to The Hidden Contract Behind a Setter" title="Direct link to The Hidden Contract Behind a Setter" translate="no">​</a></h2>
<p>Consider a loaded order with two lines. Business code changes the shipping
address, changes the quantity of one line twice, and removes the other line.
The final save needs more than the current memory representation.</p>
<p>It needs to know that:</p>
<ul>
<li class="">the order and both lines belong to one mutation unit;</li>
<li class="">the quantity has one final pending value, not two database updates;</li>
<li class="">the removed line is a deletion, not an object that happened to disappear;</li>
<li class="">each existing entity must be updated against the version originally loaded;</li>
<li class="">validation and automatic fixes must run before any database call;</li>
<li class="">a failed save must not make the in-memory graph look committed.</li>
</ul>
<p>A runtime can infer some of this from snapshots. It can place interceptors in
setters or proxies around entities. It can keep a session-level identity map.
But each mechanism creates an implicit contract, and those contracts are easy to
implement differently in different languages.</p>
<p>Rust exposed that ambiguity early. We could not depend on a web of invisible
aliases and later ask the runtime to reconstruct what had happened. We needed a
single explicit owner for mutation state.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-root-one-pending-ledger">One Root, One Pending Ledger<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#one-root-one-pending-ledger" class="hash-link" aria-label="Direct link to One Root, One Pending Ledger" title="Direct link to One Root, One Pending Ledger" translate="no">​</a></h2>
<p>Every mutable entity in a working graph now owns or references the same
<code>EntityRoot</code>. This is a technical root for pending mutation state, not a domain
aggregate root and not a tenant or authorization context.</p>
<p>The language-neutral model is deliberately small:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">EntityKey = (entityType, entityId)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">EntityRoot</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  changes: Map&lt;EntityKey, Map&lt;FieldName, NewValue&gt;&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  originalVersions: Map&lt;EntityKey, Version&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  newKeys: Set&lt;EntityKey&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  deletedKeys: Set&lt;EntityKey&gt;</span><br></div></code></pre></div></div>
<p>Generated update methods write into this root. If the same field is updated
more than once before save, the entry is overwritten with the final value. The
ledger records the state we intend to persist, so repeated writes are
last-write-wins.</p>
<p>For example, the conceptual operation:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">line</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">update_quantity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">line</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">update_quantity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>leaves one pending change for <code>quantity = 3</code>. It does not require two mutation
commands and does not lose the fact that the field was deliberately changed.</p>
<p>When a parent and its children are loaded or assembled together, they adopt the
same root. A change made through a child therefore belongs to the same ledger
consumed when the graph is saved. The save receiver is merely an entry point;
it is not the limit of mutation discovery.</p>
<p>This was the key move for Rust. Instead of trying to make every entity secretly
observe every other entity, we made mutation state an explicit shared resource
with a precise lifecycle.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-the-ledger-stores-new-values-but-not-old-values">Why the Ledger Stores New Values, but Not Old Values<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#why-the-ledger-stores-new-values-but-not-old-values" class="hash-link" aria-label="Direct link to Why the Ledger Stores New Values, but Not Old Values" title="Direct link to Why the Ledger Stores New Values, but Not Old Values" translate="no">​</a></h2>
<p>An audit record often needs both old and new values. It is tempting to copy both
into the mutation ledger, but that would duplicate state and introduce another
consistency problem.</p>
<p>A loaded entity already retains its original field state. The root records the
final intended values and the versions seen during hydration. When audit
evidence requires an old/new pair, it can combine the loaded state with the
ledger.</p>
<p>This separation also makes the purpose of the root clearer. It is a record of
pending intent, not a second complete copy of the entity graph.</p>
<p>There are limits to that choice. If an application discards the original loaded
state, it cannot later reconstruct old values from the root alone. That is
intentional: a lightweight in-memory mutation ledger should not pretend to be a
durable history system.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="checker-and-fix-are-part-of-the-same-mutation">Checker and Fix Are Part of the Same Mutation<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#checker-and-fix-are-part-of-the-same-mutation" class="hash-link" aria-label="Direct link to Checker and Fix Are Part of the Same Mutation" title="Direct link to Checker and Fix Are Part of the Same Mutation" translate="no">​</a></h2>
<p>TeaQL applies two kinds of pre-persistence behavior. A checker rejects invalid
state with a domain-facing error before the database sees it. A fix supplies
context-derived values such as creation time, update time, or a required root
reference.</p>
<p>Both operate on the pending mutation, not beside it.</p>
<p>That means a fix does not silently alter an entity through a special path. Its
change is written to the same ledger as an application update. The eventual
provider command, audit evidence, and diagnostic view all see the same final
intent.</p>
<p>The ordering is important:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">business updates</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      |</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      v</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">shared mutation ledger</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      |</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      v</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">checker and context-driven fix</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      |</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      v</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">audited save / provider commands</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      |</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      +--&gt; success: adopt authoritative versions and clear committed entries</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      |</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      `--&gt; failure: retain pending state</span><br></div></code></pre></div></div>
<p>Database constraints remain a final safety boundary, but they should not be the
first place an application learns that a required business field is missing.
The ledger gives checker and fix logic a complete graph-wide view before the
provider is called.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="failure-semantics-matter-as-much-as-the-happy-path">Failure Semantics Matter as Much as the Happy Path<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#failure-semantics-matter-as-much-as-the-happy-path" class="hash-link" aria-label="Direct link to Failure Semantics Matter as Much as the Happy Path" title="Direct link to Failure Semantics Matter as Much as the Happy Path" translate="no">​</a></h2>
<p>Dirty tracking designs often focus on detecting a change and generating an
update. The difficult part is deciding what the in-memory state means after
something goes wrong.</p>
<p>If checking rejects the mutation, no provider call should occur and the pending
ledger should remain available for correction. If the provider fails, the
runtime must not clear the ledger or claim that the new version was committed.
On success, committed entries are cleared and authoritative state—especially
generated identifiers and versions—is adopted.</p>
<p>These rules make failure observable and retry behavior understandable. They
also create useful boundaries for future diagnostics. A system can distinguish:</p>
<ul>
<li class="">what business code intended to change;</li>
<li class="">what checker or fix logic added;</li>
<li class="">what command was submitted;</li>
<li class="">whether the command committed or failed.</li>
</ul>
<p>That is already valuable without turning the design into a permanent event log.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="this-is-not-event-sourcing">This Is Not Event Sourcing<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#this-is-not-event-sourcing" class="hash-link" aria-label="Direct link to This Is Not Event Sourcing" title="Direct link to This Is Not Event Sourcing" translate="no">​</a></h2>
<p>The word “ledger” can suggest event sourcing, but this design has a different
job.</p>
<p>An event-sourced system normally persists an ordered sequence of domain events
as its source of truth. Our mutation ledger is transient pending state. It may
collapse multiple assignments to the same field into one final value, and it is
cleared after a successful save. Durable audit records can be produced from it,
but durability and replay are not properties of the ledger itself.</p>
<p>It also differs from conventional ORM dirty checking. Snapshot comparison asks,
“What is different now?” The ledger records, “What does this graph intend to
change?” The difference becomes important for deletions, optimistic versions,
context-driven fixes, failure handling, and cross-entity operations.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rust-was-the-design-review">Rust Was the Design Review<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#rust-was-the-design-review" class="hash-link" aria-label="Direct link to Rust Was the Design Review" title="Direct link to Rust Was the Design Review" translate="no">​</a></h2>
<p>There is a recurring lesson in cross-language framework work: a feature that is
easy to hide in one language may still be poorly specified.</p>
<p>Garbage collection, reference semantics, dynamic interception, or framework
proxies can make a convenient API possible without forcing its ownership model
into the open. Rust removes many of those escape routes. That can feel like
friction, but the friction is information. It tells us where the architecture
depends on an unnamed owner, an implicit lifetime, or an ambiguous side effect.</p>
<p>In this case, Rust forced us to identify the real unit of mutation. It was not
one entity and it was not whichever object happened to receive <code>save</code>. It was
the set of pending changes attached to a shared object graph.</p>
<p>Once that was explicit, the design became easier to explain, test, and port.
The surprising benefit was not merely that the Rust runtime worked. The other
runtimes acquired a stronger contract too.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="from-one-rust-problem-to-seven-conforming-runtimes">From One Rust Problem to Seven Conforming Runtimes<a href="https://teaql.io/blog/rust-made-object-mutation-explicit#from-one-rust-problem-to-seven-conforming-runtimes" class="hash-link" aria-label="Direct link to From One Rust Problem to Seven Conforming Runtimes" title="Direct link to From One Rust Problem to Seven Conforming Runtimes" translate="no">​</a></h2>
<p>TeaQL now applies the same mutation-ledger semantics in Rust, Java, Python, Go,
.NET, Swift, and TypeScript. The APIs remain idiomatic to each language, but the
observable behavior is shared: graph-wide roots, final field values, original
versions, new/delete classification, checker-before-provider behavior, and
clear success and failure transitions.</p>
<p>We retain executable cross-language evidence in the
<a href="https://github.com/teaql/teaql-conformance" target="_blank" rel="noopener noreferrer" class="">TeaQL conformance repository</a>,
rather than treating matching documentation as proof. The current fixture
constructs or loads a parent with children, mutates both entity types, updates
one field twice, marks a child for deletion, and saves through the ordinary
audited path. It checks the ledger before save, the provider commands during
save, and ledger state after rejection or success.</p>
<p>The implementation began in <a href="https://github.com/teaql/teaql-rs" target="_blank" rel="noopener noreferrer" class="">TeaQL Rust</a>.
The other six implementations—<a href="https://github.com/teaql/teaql-java" target="_blank" rel="noopener noreferrer" class="">Java</a>,
<a href="https://github.com/teaql/teaql-python" target="_blank" rel="noopener noreferrer" class="">Python</a>,
<a href="https://github.com/teaql/teaql-golang" target="_blank" rel="noopener noreferrer" class="">Go</a>,
<a href="https://github.com/teaql/teaql-dotnet" target="_blank" rel="noopener noreferrer" class="">.NET</a>,
<a href="https://github.com/teaql/teaql-swift" target="_blank" rel="noopener noreferrer" class="">Swift</a>, and
<a href="https://github.com/teaql/teaql-ts" target="_blank" rel="noopener noreferrer" class="">TypeScript</a>—then adopted the same design.</p>
<p>What started as a solution to Rust's mutation constraints became one of the
clearest pieces of our cross-language runtime architecture. Rust did not merely
make us work harder. It made the hidden contract visible—and once visible, the
contract could finally become consistent.</p>]]></content:encoded>
            <category>teaql</category>
            <category>rust</category>
            <category>mutation</category>
            <category>persistence</category>
            <category>architecture</category>
            <category>cross-language</category>
        </item>
        <item>
            <title><![CDATA[How AI Acquires Professional Capabilities Beyond the Model]]></title>
            <link>https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model</link>
            <guid>https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model</guid>
            <pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[RAG can help an AI find private knowledge. Harness engineering turns that knowledge into professional capabilities that can be built, verified, constrained, and audited.]]></description>
            <content:encoded><![CDATA[<p>A foundation model can know a great deal about programming, finance, manufacturing, medicine, and law. It still cannot know the private operating knowledge of a particular organization: an internal approval rule, a proprietary engineering method, an undocumented exception, or the reason one production procedure is trusted while another is prohibited.</p>
<p>This gap is often described as a knowledge-access problem. Give the model the right documents, retrieve the right passages, and it will know what to do.</p>
<p>Retrieval is necessary, but it is not sufficient.</p>
<p>The real enterprise question is not only:</p>
<blockquote>
<p>Can the AI find the knowledge?</p>
</blockquote>
<p>It is:</p>
<blockquote>
<p>Can the AI turn that knowledge into a correct, verifiable, and constrained capability?</p>
</blockquote>
<p>Our work with TeaQL suggests a three-layer answer: <strong>Skill</strong>, <strong>Build Harness</strong>, and <strong>Runtime Harness</strong>. A Skill keeps the agent's direction and method sound. A Build Harness makes the constructed artifact mechanically verifiable. A Runtime Harness keeps actual execution inside engineering, security, permission, resource, and audit boundaries.</p>
<p>Together, these layers provide a practical way to give AI capabilities that do not exist inside the model itself.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="knowledge-is-not-yet-capability">Knowledge Is Not Yet Capability<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#knowledge-is-not-yet-capability" class="hash-link" aria-label="Direct link to Knowledge Is Not Yet Capability" title="Direct link to Knowledge Is Not Yet Capability" translate="no">​</a></h2>
<p>Suppose an experienced engineer knows how to respond to an unusual vibration pattern in a machine. The correct response may depend on load, temperature, lubrication state, recent maintenance, and the cost of an unnecessary shutdown. A document can record those factors. Retrieval can place the relevant paragraph in the model's context.</p>
<p>But professional capability involves more than repeating that paragraph. The engineer must:</p>
<ul>
<li class="">recognize when the procedure applies;</li>
<li class="">gather the required evidence;</li>
<li class="">distinguish a warning from a critical condition;</li>
<li class="">use approved diagnostic operations;</li>
<li class="">respect authority and safety boundaries;</li>
<li class="">produce a decision that another person can inspect;</li>
<li class="">act only when the evidence and permission are sufficient.</li>
</ul>
<p>The same distinction appears in software delivery. An AI may retrieve a database convention or a domain rule and still invent a method name, omit a tenant boundary, save an invalid object graph, or run an unsafe operation. It has access to knowledge, but it does not yet possess a reliable capability.</p>
<p>This distinction matters most for knowledge that was never present in model training:</p>
<ul>
<li class="">private enterprise policies and operating procedures;</li>
<li class="">domain-specific methods and terminology;</li>
<li class="">proprietary workflows and decision rules;</li>
<li class="">local architecture conventions;</li>
<li class="">engineering lessons learned from previous incidents;</li>
<li class="">tacit review standards used by experienced practitioners.</li>
</ul>
<p>These are not special cases. They are where much of an organization's real advantage lives.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rag-finds-knowledge-harness-engineering-operationalizes-it">RAG Finds Knowledge; Harness Engineering Operationalizes It<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#rag-finds-knowledge-harness-engineering-operationalizes-it" class="hash-link" aria-label="Direct link to RAG Finds Knowledge; Harness Engineering Operationalizes It" title="Direct link to RAG Finds Knowledge; Harness Engineering Operationalizes It" translate="no">​</a></h2>
<p>Retrieval-augmented generation is well suited to locating relevant information:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Question</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Retrieval</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Relevant private context</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Model response</span><br></div></code></pre></div></div>
<p>It can answer, “Which policy applies?” or “What does our design guide say?” It can reduce hallucination caused by missing context and make private documents available without retraining a foundation model.</p>
<p>However, retrieval does not by itself answer several harder questions:</p>
<ul>
<li class="">Did the agent apply the correct procedure?</li>
<li class="">Is the produced model or code structurally valid?</li>
<li class="">Does the result preserve domain invariants?</li>
<li class="">Is the requested action permitted for this identity and tenant?</li>
<li class="">Are resource limits and side effects controlled?</li>
<li class="">Can the organization reconstruct what happened and why?</li>
</ul>
<p>Harness engineering addresses this next step:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Private knowledge</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Procedural guidance</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Constrained construction</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Verification</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Governed execution</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Evidence</span><br></div></code></pre></div></div>
<p>RAG and harness engineering are complementary. RAG supplies relevant context. A harness turns context into an operating discipline, an executable artifact, and a controlled action.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-three-layer-method">The Three-Layer Method<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#the-three-layer-method" class="hash-link" aria-label="Direct link to The Three-Layer Method" title="Direct link to The Three-Layer Method" translate="no">​</a></h2>
<p>The method can be summarized as:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Skill</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  keeps direction and method correct</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Build Harness</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  makes the constructed artifact correct</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Runtime Harness</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  keeps actual execution correct</span><br></div></code></pre></div></div>
<p>Each layer addresses a different failure mode. None can substitute completely for the others.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="layer-1-skill-keeps-direction-and-method-correct">Layer 1: Skill Keeps Direction and Method Correct<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#layer-1-skill-keeps-direction-and-method-correct" class="hash-link" aria-label="Direct link to Layer 1: Skill Keeps Direction and Method Correct" title="Direct link to Layer 1: Skill Keeps Direction and Method Correct" translate="no">​</a></h2>
<p>A Skill gives the agent a compact operating method. It explains the goal, the important stages, the evidence to inspect, when to use a Tool, when to repair a result, and when human judgment is required.</p>
<p>For example, an internal incident-response Skill might tell the agent to:</p>
<ol>
<li class="">identify the affected service and business impact;</li>
<li class="">gather current telemetry before proposing a cause;</li>
<li class="">compare the evidence with known failure patterns;</li>
<li class="">use read-only diagnostics before considering a mutation;</li>
<li class="">escalate when the proposed action crosses a declared risk threshold;</li>
<li class="">record the evidence behind the conclusion.</li>
</ol>
<p>This is far more useful than a collection of retrieved paragraphs because it organizes knowledge into a procedure.</p>
<p>But a Skill remains guidance expressed in language. It can influence a probabilistic model; it cannot guarantee that every required field exists, every invariant holds, or every prohibited action is blocked. As Skills grow into exhaustive rule catalogs, they also compete for context, drift away from the implemented system, and become harder for the model to apply consistently.</p>
<p>The right role for a Skill is therefore stable direction and method—not mechanical enforcement.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="layer-2-the-build-harness-makes-the-artifact-correct">Layer 2: The Build Harness Makes the Artifact Correct<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#layer-2-the-build-harness-makes-the-artifact-correct" class="hash-link" aria-label="Direct link to Layer 2: The Build Harness Makes the Artifact Correct" title="Direct link to Layer 2: The Build Harness Makes the Artifact Correct" translate="no">​</a></h2>
<p>Once the agent begins constructing something—a domain model, application, workflow, configuration, report, or decision package—correctness must move into executable feedback loops.</p>
<p>A Build Harness may include:</p>
<ul>
<li class="">schemas and type systems;</li>
<li class="">domain-specific languages;</li>
<li class="">linters and static analyzers;</li>
<li class="">policy evaluators;</li>
<li class="">deterministic generators;</li>
<li class="">compilers;</li>
<li class="">unit, integration, and acceptance tests;</li>
<li class="">simulations and benchmark cases;</li>
<li class="">structured error reports that support repair.</li>
</ul>
<p>These mechanisms do not merely tell the agent what correctness means. They test the artifact and return evidence.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Agent proposes an artifact</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Evaluate</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Return structured failures</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Repair</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Re-evaluate</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Generate or package</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Test</span><br></div></code></pre></div></div>
<p>This loop is especially important when teaching an AI a new technology or an internal engineering method. A long prompt can describe the method, but a validator can reject an invalid representation. A compiler can detect an invented interface. A test can prove that a critical scenario works. A deterministic generator can preserve rules the model should not reproduce from memory.</p>
<p>The build layer changes the meaning of “the AI knows how to do it.” The claim no longer depends only on whether the model can produce a convincing answer. It depends on whether the result passes the organization's executable definition of correctness.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="layer-3-the-runtime-harness-keeps-execution-correct">Layer 3: The Runtime Harness Keeps Execution Correct<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#layer-3-the-runtime-harness-keeps-execution-correct" class="hash-link" aria-label="Direct link to Layer 3: The Runtime Harness Keeps Execution Correct" title="Direct link to Layer 3: The Runtime Harness Keeps Execution Correct" translate="no">​</a></h2>
<p>A correct artifact can still be used incorrectly.</p>
<p>Production execution introduces identity, authority, current state, concurrency, resource limits, sensitive data, side effects, and failure recovery. These conditions cannot be settled permanently during generation. They must be enforced when an action is attempted.</p>
<p>A Runtime Harness provides controls such as:</p>
<ul>
<li class="">authenticated identity and request context;</li>
<li class="">authorization and tenant boundaries;</li>
<li class="">approved, semantically narrow Tools instead of unrestricted access;</li>
<li class="">transaction and state-transition guards;</li>
<li class="">input, output, and policy validation;</li>
<li class="">rate, time, memory, and cost limits;</li>
<li class="">sandboxing and network boundaries;</li>
<li class="">approval gates for consequential actions;</li>
<li class="">idempotency, rollback, and recovery mechanisms;</li>
<li class="">logs, provenance, and audit evidence;</li>
<li class="">monitoring and the ability to stop execution.</li>
</ul>
<p>This layer answers questions that no Skill can reliably answer in prose: Does this user have permission now? Is this transition valid from the current state? Has the spending limit been reached? Is the target inside the approved environment? Can the exact action and its justification be reconstructed later?</p>
<p>The Runtime Harness is where advice becomes authority-aware action.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="teaql-as-a-concrete-case">TeaQL as a Concrete Case<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#teaql-as-a-concrete-case" class="hash-link" aria-label="Direct link to TeaQL as a Concrete Case" title="Direct link to TeaQL as a Concrete Case" translate="no">​</a></h2>
<p>TeaQL is useful here not because every enterprise should adopt the same technology, but because it makes the three layers visible in one engineering workflow.</p>
<p>The TeaQL agent workflow begins with a lightweight Skill. The Skill directs the agent to understand the business requirement, express it as a typed domain contract, evaluate the contract, repair reported problems, generate the application, and provide concrete completion evidence. It describes the path without attempting to embed every modeling and programming rule in the prompt.</p>
<p>The build layer then carries the detailed correctness burden. The Generation Service evaluates the domain model and returns structured reports. Deterministic generation projects an accepted model into code and model-aware APIs. Generated local guidance exposes the current interfaces. Compilers and tests reject invented methods, invalid types, and broken behavior.</p>
<p>The runtime layer constrains what the resulting application can do. Queries and writes execute through a user context. Read operations carry purpose and comments; mutations carry audit descriptions. Provider and repository boundaries control persistence. Policies, tenant rules, generated business APIs, and runtime checks sit between AI-generated application logic and the underlying data systems.</p>
<p>In simplified form:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Business requirement</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Skill-guided domain modeling</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Evaluation and repair</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Deterministic generation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Compiler and test evidence</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; User-context execution</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Policy, permission, and audit controls</span><br></div></code></pre></div></div>
<p>The important result is not that the model memorizes TeaQL. It is that a general-purpose model can use a capability that was not part of its training, while detailed rules remain in the systems best able to enforce them.</p>
<p>This is also why the case should not be reduced to code generation. The same architecture applies whenever professional knowledge must cross the boundary from explanation to responsible execution.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="from-internal-knowledge-to-executable-knowledge">From Internal Knowledge to Executable Knowledge<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#from-internal-knowledge-to-executable-knowledge" class="hash-link" aria-label="Direct link to From Internal Knowledge to Executable Knowledge" title="Direct link to From Internal Knowledge to Executable Knowledge" translate="no">​</a></h2>
<p>Consider four examples.</p>
<p>An insurance company may have a proprietary claims-review method. RAG can retrieve the policy and prior cases. A Skill can define the review sequence. A Build Harness can validate that the decision package contains the required evidence and calculations. A Runtime Harness can enforce adjuster authority, protect customer data, and audit the final action.</p>
<p>A manufacturer may have an internal process for diagnosing equipment. A Skill can guide evidence collection. Diagnostic Tools and simulations can verify the proposed intervention. Runtime controls can prevent an agent from changing machine parameters outside an approved range.</p>
<p>A bank may have a private credit-exception workflow. Retrieval can provide policy context. A Skill can distinguish ordinary assessment from exception handling. Validators can check the completeness and consistency of the case. Runtime permissions and approval gates can ensure that a recommendation does not become an unauthorized decision.</p>
<p>A software organization may have years of engineering experience encoded across code review comments, incident reports, and unwritten conventions. A Skill can express the stable workflow. Build checks can enforce architectural rules and test critical cases. Runtime boundaries can restrict deployment targets, secrets, infrastructure changes, and production access.</p>
<p>In every example, the useful transformation is:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Information</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Procedure</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Verifiable artifact</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Constrained action</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Auditable evidence</span><br></div></code></pre></div></div>
<p>That is what it means to turn organizational knowledge into executable knowledge.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-each-rule-should-live">Where Each Rule Should Live<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#where-each-rule-should-live" class="hash-link" aria-label="Direct link to Where Each Rule Should Live" title="Direct link to Where Each Rule Should Live" translate="no">​</a></h2>
<p>A practical design test is to ask what kind of rule has failed:</p>
<table><thead><tr><th>Question</th><th>Best home</th></tr></thead><tbody><tr><td>What goal and workflow should the agent follow?</td><td>Skill</td></tr><tr><td>What private context is relevant to this case?</td><td>Retrieval and context layer</td></tr><tr><td>What concepts, relationships, and invariants define the domain?</td><td>Domain or world model</td></tr><tr><td>Can this artifact be shown to be structurally and behaviorally valid?</td><td>Build Harness</td></tr><tr><td>Is this actor allowed to perform this action in the current state?</td><td>Runtime Harness</td></tr><tr><td>What happened, why, and with whose authority?</td><td>Runtime evidence and audit</td></tr></tbody></table>
<p>When a failure repeats, adding another paragraph to a prompt is rarely the strongest long-term fix. Stable procedural guidance belongs in a Skill. Domain meaning belongs in an explicit model. Mechanical correctness belongs in validators and tests. Authority and side-effect control belong at runtime.</p>
<p>This division keeps the model's context smaller while making the surrounding system stronger.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-capability-formula-for-enterprise-ai">A Capability Formula for Enterprise AI<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#a-capability-formula-for-enterprise-ai" class="hash-link" aria-label="Direct link to A Capability Formula for Enterprise AI" title="Direct link to A Capability Formula for Enterprise AI" translate="no">​</a></h2>
<p>The method can be expressed as a compact systems formula:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Enterprise AI Capability</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  = Foundation Model</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  + Domain Context</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  + Skill</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  + Build Assurance</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  + Runtime Assurance</span><br></div></code></pre></div></div>
<p>The foundation model contributes general reasoning and generation. Domain context supplies knowledge the model did not contain. The Skill provides operating method. Build assurance makes artifacts verifiable. Runtime assurance makes real actions governable.</p>
<p>If any of the later layers is missing, the system tends to fall back into one of two weak modes: an AI that can discuss the organization's knowledge but cannot reliably act, or an AI that can act but cannot be trusted with consequential work.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-next-step-after-retrieval">The Next Step After Retrieval<a href="https://teaql.io/blog/how-ai-acquires-professional-capabilities-beyond-the-model#the-next-step-after-retrieval" class="hash-link" aria-label="Direct link to The Next Step After Retrieval" title="Direct link to The Next Step After Retrieval" translate="no">​</a></h2>
<p>Enterprise AI is moving through three progressively harder questions:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Knowledge:  Can the model know?</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Retrieval:  Can it find the relevant private knowledge?</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Execution:  Can it apply that knowledge correctly and safely?</span><br></div></code></pre></div></div>
<p>The third question is not solved by a larger context window or a better search index alone. It requires engineering around the model.</p>
<p>TeaQL offers one concrete example of that transition: lightweight procedural guidance, deterministic construction and verification, and a constrained runtime boundary. The broader method is technology-independent. Any organization can apply it to its own internal knowledge, specialist methods, proprietary processes, and accumulated engineering experience.</p>
<p>The goal is not to make a foundation model contain every organization's expertise. The goal is to build systems through which a capable model can use expertise it was never trained on—and do so with evidence, limits, and accountability.</p>]]></content:encoded>
            <category>ai</category>
            <category>agents</category>
            <category>enterprise-ai</category>
            <category>harness-engineering</category>
            <category>agent-skill</category>
            <category>tools</category>
            <category>runtime</category>
            <category>teaql</category>
        </item>
        <item>
            <title><![CDATA[Beyond SQL Dialects: A Governed Business Query Language for AI Agents]]></title>
            <link>https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents</link>
            <guid>https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents</guid>
            <pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How TeaQL lets AI agents compose new business queries without exposing raw SQL, physical schemas, or trusted runtime context.]]></description>
            <content:encoded><![CDATA[<p>An AI agent becomes much more useful when it can answer questions that an
application team did not anticipate when the system was built.</p>
<p>Consider this request:</p>
<blockquote>
<p>Find customers who placed more than three orders in the last 30 days, have a
refund rate above 20%, and still have an unresolved support ticket.</p>
</blockquote>
<p>A conventional application may not have an endpoint for that exact question.
A model with unrestricted SQL access could try to construct it, but it would
also need to know the physical schema, joins, enum encodings, tenant filters,
authorization rules, soft-delete conventions, and database dialect. That is a
large and dangerous contract to place in a prompt.</p>
<p>TeaQL offers a different boundary:</p>
<blockquote>
<p>Give the model composable business semantics, not database authority.</p>
</blockquote>
<p>TeaQL sits above SQL dialects as a governed business query language. The model
can combine approved domain concepts into a query that has never been exposed
as a dedicated endpoint, while the application retains control of identity,
permissions, limits, audit, and execution.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-gap-between-fixed-apis-and-raw-sql">The Gap Between Fixed APIs and Raw SQL<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#the-gap-between-fixed-apis-and-raw-sql" class="hash-link" aria-label="Direct link to The Gap Between Fixed APIs and Raw SQL" title="Direct link to The Gap Between Fixed APIs and Raw SQL" translate="no">​</a></h2>
<p>Most agent-to-data integrations begin at one of two extremes.</p>
<p>At one extreme, the application exposes a fixed set of narrow API operations:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">getCustomerById</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">listOpenOrders</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">findOverdueInvoices</span><br></div></code></pre></div></div>
<p>These operations are easy to govern, but their composition space is limited.
Every new question may require another endpoint, deployment, and integration.</p>
<p>At the other extreme, the application gives the model a generic SQL tool:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">executeSql(sql: string)</span><br></div></code></pre></div></div>
<p>This is flexible, but the abstraction boundary is wrong. SQL exposes storage
mechanics rather than business capabilities. A syntactically valid query can
still violate tenant isolation, reveal sensitive fields, scan an unreasonable
amount of data, or encode the wrong business meaning.</p>
<p>TeaQL occupies the space between them:</p>
<table><thead><tr><th>Boundary</th><th>Composition</th><th>Governance</th><th>Coupling</th></tr></thead><tbody><tr><td>Fixed application APIs</td><td>Low to medium</td><td>Strong</td><td>Coupled to predefined use cases</td></tr><tr><td>Raw SQL</td><td>High</td><td>Difficult</td><td>Coupled to schema and database dialect</td></tr><tr><td>TeaQL business queries</td><td>High within declared capabilities</td><td>Enforced by the runtime</td><td>Coupled to stable domain semantics</td></tr></tbody></table>
<p>The objective is not unrestricted flexibility. It is <strong>governed query
composition</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sql-describes-storage-teaql-describes-the-business">SQL Describes Storage; TeaQL Describes the Business<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#sql-describes-storage-teaql-describes-the-business" class="hash-link" aria-label="Direct link to SQL Describes Storage; TeaQL Describes the Business" title="Direct link to SQL Describes Storage; TeaQL Describes the Business" translate="no">​</a></h2>
<p>SQL is excellent at describing how to retrieve and transform rows. It speaks
in tables, columns, joins, predicates, grouping, ordering, and database-specific
functions.</p>
<p>An agent working on behalf of a user needs a different vocabulary:</p>
<ul>
<li class="">Customer, Order, Refund, and Support Ticket;</li>
<li class="">active, overdue, unresolved, and eligible;</li>
<li class="">relationships between business objects;</li>
<li class="">fields that may be filtered, projected, aggregated, or sorted;</li>
<li class="">the current user's tenant and permitted data scope;</li>
<li class="">the purpose of the query and the limits of the operation.</li>
</ul>
<p>TeaQL maps that business vocabulary to generated, typed query APIs. Database
providers remain responsible for translating the resulting request into the
appropriate SQL and parameter representation.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Natural-language request</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; model-selected business query</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; TeaQL domain semantics and runtime policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; PostgreSQL, MySQL, Oracle, SQL Server, SQLite, or another provider</span><br></div></code></pre></div></div>
<p>The database still executes SQL. The important change is that SQL is no longer
the contract between the model and the application.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-queries-without-new-database-authority">New Queries Without New Database Authority<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#new-queries-without-new-database-authority" class="hash-link" aria-label="Direct link to New Queries Without New Database Authority" title="Direct link to New Queries Without New Database Authority" translate="no">​</a></h2>
<p>Dynamic query composition matters because users rarely ask only the questions
that developers predicted.</p>
<p>A TeaQL query can combine declared capabilities such as:</p>
<ul>
<li class="">filters over typed business properties;</li>
<li class="">relationship traversal and nested selection;</li>
<li class="">projection of an approved field set;</li>
<li class="">sorting, pagination, grouping, and aggregation;</li>
<li class="">reusable domain predicates;</li>
<li class="">runtime policies applied through the current context.</li>
</ul>
<p>These pieces can express a new question without creating a new repository
method for every combination.</p>
<p>The model should not emit TeaQL source code directly. Instead, it should call a
tool with a constrained, machine-readable query specification. The server
validates that specification and maps it to generated TeaQL APIs.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"entity"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Order"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"filters"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"field"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"status"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"operator"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"is"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"PAID"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"field"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"createdAt"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"operator"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"after"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-08-01T00:00:00Z"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"select"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"customerName"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"createdAt"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"orderBy"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"field"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"createdAt"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token property" style="color:#36acaa">"direction"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"desc"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"limit"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>This is not a second textual query language for the model to improvise. It is a
validated capability document. Only registered entities, fields, operators,
relations, and limits are accepted.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-model-does-not-receive-trusted-context">The Model Does Not Receive Trusted Context<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#the-model-does-not-receive-trusted-context" class="hash-link" aria-label="Direct link to The Model Does Not Receive Trusted Context" title="Direct link to The Model Does Not Receive Trusted Context" translate="no">​</a></h2>
<p>The model proposes what it wants to query. The server decides under whose
authority the query runs.</p>
<p>TeaQL execution uses a trusted <code>context</code> selected by the application. It can
carry identity, tenant, authorization policy, data services, audit facilities,
and other runtime resources. That context is captured server-side and is never
accepted as model input.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Model-generated query specification</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; schema and capability validation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; server-owned context</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; authorization and tenant policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; TeaQL request execution</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; bounded, projected result</span><br></div></code></pre></div></div>
<p>This separation prevents the model from choosing another tenant, replacing a
data service, or granting itself a permission through tool arguments.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="governance-is-more-than-preventing-bad-sql">Governance Is More Than Preventing Bad SQL<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#governance-is-more-than-preventing-bad-sql" class="hash-link" aria-label="Direct link to Governance Is More Than Preventing Bad SQL" title="Direct link to Governance Is More Than Preventing Bad SQL" translate="no">​</a></h2>
<p>Removing raw SQL is useful, but it is not the complete security model. A
governed business query also needs explicit decisions about:</p>
<ul>
<li class="">which entities and relationships an agent may use;</li>
<li class="">which fields may be filtered or returned;</li>
<li class="">which operators and aggregates are available;</li>
<li class="">maximum page size, traversal depth, and execution cost;</li>
<li class="">sensitive-field masking and result projection;</li>
<li class="">authorization and tenant isolation;</li>
<li class="">query purpose, audit metadata, and telemetry;</li>
<li class="">safe error messages returned to the model.</li>
</ul>
<p>The model's prompt is guidance. These controls belong in deterministic server
code and runtime policy.</p>
<p>The useful distinction is:</p>
<blockquote>
<p>SQL permissions answer what a database connection can execute. TeaQL
capabilities answer what this user, through this agent, may do in this
business context.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dynamic-reads-explicit-business-actions">Dynamic Reads, Explicit Business Actions<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#dynamic-reads-explicit-business-actions" class="hash-link" aria-label="Direct link to Dynamic Reads, Explicit Business Actions" title="Direct link to Dynamic Reads, Explicit Business Actions" translate="no">​</a></h2>
<p>The freedom to compose reads should not imply arbitrary writes.</p>
<p>Queries are naturally exploratory. Within declared limits, it is reasonable
for an agent to combine filters and projections to answer a new question.
Mutations have different risks: they may trigger workflows, violate state
transitions, affect money, or require human confirmation.</p>
<p>TeaQL therefore benefits from an asymmetric boundary:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Read request</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; constrained dynamic query</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; validation and policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; bounded result</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Write request</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; explicit business action</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; input validation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; user approval when required</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; authorization and domain validation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; audited save</span><br></div></code></pre></div></div>
<p>An agent may dynamically discover orders that qualify for review. Creating a
refund, approving it, or closing an order should still happen through explicit
actions such as <code>createRefundRequest</code>, <code>approveRefund</code>, or <code>closeOrder</code>.</p>
<p>This preserves useful query flexibility without turning the agent into a
general-purpose database administrator.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-business-language-across-runtimes-and-databases">One Business Language Across Runtimes and Databases<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#one-business-language-across-runtimes-and-databases" class="hash-link" aria-label="Direct link to One Business Language Across Runtimes and Databases" title="Direct link to One Business Language Across Runtimes and Databases" translate="no">​</a></h2>
<p>Database portability is often described as hiding placeholder syntax or
pagination differences. For agents, the larger benefit is semantic stability.</p>
<p>The same business concept should retain its meaning when an application moves
between database providers or when a TeaQL service is implemented in a
different supported language. The model-facing tool should not need to learn
whether a timestamp comparison becomes a PostgreSQL expression, an Oracle
expression, or a SQLite expression.</p>
<p>That creates a layered contract:</p>
<table><thead><tr><th>Layer</th><th>Stable responsibility</th></tr></thead><tbody><tr><td>Model</td><td>Select a tool and supply schema-valid business arguments</td></tr><tr><td>TeaQL AI SDK</td><td>Convert allowed capabilities into model-facing tools</td></tr><tr><td>TeaQL runtime</td><td>Apply context, domain semantics, policy, audit, and execution rules</td></tr><tr><td>Database provider</td><td>Produce correct parameterized operations for its database</td></tr></tbody></table>
<p>Models and database providers can change independently while the business
language remains recognizable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-practical-agent-interaction">A Practical Agent Interaction<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#a-practical-agent-interaction" class="hash-link" aria-label="Direct link to A Practical Agent Interaction" title="Direct link to A Practical Agent Interaction" translate="no">​</a></h2>
<p>Suppose a user asks:</p>
<blockquote>
<p>Show me secondary schools created this year whose contact phone is missing.</p>
</blockquote>
<p>The interaction can follow this path:</p>
<ol>
<li class="">The model selects an approved school-search tool.</li>
<li class="">It supplies typed filters for school type, creation date, and an explicitly
null contact phone.</li>
<li class="">The server validates the query against the published capability schema.</li>
<li class="">The application attaches its trusted TeaQL context.</li>
<li class="">Runtime policy applies authorization, tenant filters, projection, and result
limits.</li>
<li class="">The database provider executes parameterized SQL in its own dialect.</li>
<li class="">The tool returns a bounded business result, not unrestricted database rows.</li>
<li class="">The model explains the result to the user.</li>
</ol>
<p>If the user then asks the agent to update a phone number, the agent switches to
an explicit write capability with validation, approval, and audit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-role-of-teaqlai-sdk">The Role of <code>@teaql/ai-sdk</code><a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#the-role-of-teaqlai-sdk" class="hash-link" aria-label="Direct link to the-role-of-teaqlai-sdk" title="Direct link to the-role-of-teaqlai-sdk" translate="no">​</a></h2>
<p>The <a href="https://github.com/teaql/teaql-ai-sdk" target="_blank" rel="noopener noreferrer" class="">TeaQL AI SDK</a> is designed to connect
TeaQL business capabilities to model tool calling. It complements an agent SDK;
it does not provide a model or replace the agent loop.</p>
<p>The agent SDK handles model providers, conversations, streaming, and tool-call
orchestration. TeaQL provides the business-data boundary underneath:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Model and agent loop</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; TeaQL AI SDK tools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; TeaQL runtime context and policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; business data</span><br></div></code></pre></div></div>
<p>For a concrete example of explicit capabilities, approval, server-owned
context, safe failures, and audited writes, read
<a class="" href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql">Build a Safe SQL Agent Without Giving the Model SQL Access</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="beyond-the-dialect-boundary">Beyond the Dialect Boundary<a href="https://teaql.io/blog/beyond-sql-dialects-governed-business-query-language-ai-agents#beyond-the-dialect-boundary" class="hash-link" aria-label="Direct link to Beyond the Dialect Boundary" title="Direct link to Beyond the Dialect Boundary" translate="no">​</a></h2>
<p>TeaQL does not need to replace SQL to move the application boundary above it.
SQL remains an effective execution language for relational databases. TeaQL
provides the stable business language that applications and AI agents can use
without depending directly on physical schema or dialect.</p>
<p>The resulting proposition is simple:</p>
<blockquote>
<p>Ask questions your application has never implemented, without giving AI
unrestricted SQL access.</p>
</blockquote>
<p>Or, in architectural terms:</p>
<blockquote>
<p>TeaQL is a governed business query language above SQL dialects: composable
like a query, governed like an application API, and designed for AI agents.</p>
</blockquote>]]></content:encoded>
            <category>teaql</category>
            <category>ai</category>
            <category>agents</category>
            <category>sql</category>
            <category>query-language</category>
            <category>architecture</category>
            <category>governance</category>
        </item>
        <item>
            <title><![CDATA[Build a Safe SQL Agent Without Giving the Model SQL Access]]></title>
            <link>https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql</link>
            <guid>https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql</guid>
            <pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How TeaQL turns an explicit business-capability allowlist into typed, auditable Vercel AI SDK tools while keeping context, authorization, credentials, and internal failures on the server.]]></description>
            <content:encoded><![CDATA[<p>The fastest way to connect an AI agent to application data is often a generic
SQL tool. Give the model a schema, accept a SQL string, run it, and return the
rows.</p>
<p>That is also where a prototype can quietly become a production security and
maintenance problem.</p>
<p>The model must understand physical table names, joins, nullable columns,
tenant boundaries, authorization rules, and mutation policy. Database details
become part of the prompt contract. A schema change can invalidate that
contract, and a broadly capable SQL tool exposes much more authority than most
business tasks require.</p>
<p>TeaQL takes a different approach:</p>
<blockquote>
<p>Don't give your AI agent unrestricted SQL. Give it a typed business language.</p>
</blockquote>
<p>The open-source <a href="https://github.com/teaql/teaql-ai-sdk" target="_blank" rel="noopener noreferrer" class=""><code>@teaql/ai-sdk</code></a>
adapter converts an explicit allowlist of business capabilities into native
Vercel AI SDK tools. The model sees operations such as
<code>findSchoolsMissingContact</code> and <code>updateSchoolContactPhone</code>. The server keeps the
TeaQL context, runtime resources, authorization state, credentials, and
internal failures.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-missing-layer-beneath-an-agent-sdk">The missing layer beneath an agent SDK<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#the-missing-layer-beneath-an-agent-sdk" class="hash-link" aria-label="Direct link to The missing layer beneath an agent SDK" title="Direct link to The missing layer beneath an agent SDK" translate="no">​</a></h2>
<p>The Vercel AI SDK already provides the agent loop, tool calling, streaming,
model-provider integration, and UI primitives. TeaQL does not reproduce those
features. It supplies the governed business-data layer beneath them:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">User conversation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Vercel AI SDK agent</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; typed TeaQL business tools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; UserContext, policy, audit and runtime services</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; database</span><br></div></code></pre></div></div>
<p>A generic SQL tool exposes an implementation mechanism:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> executeSql </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  description</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Execute SQL against the application database"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  inputSchema</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">object</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> sql</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">execute</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> sql </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> database</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sql</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>A TeaQL capability exposes an application operation:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> findSchoolsMissingContact </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">defineTeaQLCapability</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'findSchoolsMissingContact'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  description</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'Find schools of a given type whose contact phone is explicitly null.'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  inputSchema</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">object</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    schoolType</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'PRIMARY'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'SECONDARY'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  risk</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'read'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">execute</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> input </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    context</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">requireResource</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name">SchoolRepository</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'schoolRepository'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findMissingContact</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">input</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">schoolType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The second tool does not ask the model to invent a table name, encode an enum
as the right database value, or decide which columns are safe to return. Its
name and schema describe a bounded business capability.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deny-by-absence">Deny by absence<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#deny-by-absence" class="hash-link" aria-label="Direct link to Deny by absence" title="Direct link to Deny by absence" translate="no">​</a></h2>
<p><code>createTeaQLTools</code> receives the complete set of capabilities available to one
agent. A capability that is not passed to the function does not exist in the
AI SDK toolset.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> tools </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createTeaQLTools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  capabilities</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    findSchoolsMissingContact</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    updateSchoolContactPhone</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>An optional runtime allowlist can narrow that set for a particular user or
agent:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> readOnlyTools </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createTeaQLTools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  capabilities</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> schoolCapabilities</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  allow</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'findSchoolsMissingContact'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Unknown allowlist names and duplicate capability names fail during startup.
They do not silently produce a weaker or unexpectedly empty policy.</p>
<p>This is intentionally different from generating five CRUD tools for every
entity. Large domains can contain hundreds of entities. Automatically exposing
every operation creates tool-selection noise and grants the agent authority it
does not need. TeaQL models the smaller set of operations that make sense for
the agent's job.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-model-never-receives-usercontext">The model never receives <code>UserContext</code><a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#the-model-never-receives-usercontext" class="hash-link" aria-label="Direct link to the-model-never-receives-usercontext" title="Direct link to the-model-never-receives-usercontext" translate="no">​</a></h2>
<p>The input schema is model-visible. The TeaQL <code>UserContext</code> is not.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> context </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">UserContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertResource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'dataService'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertResource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'authorization'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authorization</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> tools </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createTeaQLTools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> capabilities </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p><code>context</code> is captured in the server-side execute closure. It carries trusted
runtime resources, identity and policy selected by the application. The model
cannot construct it, replace its data service, choose another tenant, or add a
permission through tool input.</p>
<p>This follows a broader TeaQL API rule: business execution receives one trusted
<code>context</code>; process-level runtime ownership and provider installation are not
mixed into model-generated parameters.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="approval-and-authorization-solve-different-problems">Approval and authorization solve different problems<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#approval-and-authorization-solve-different-problems" class="hash-link" aria-label="Direct link to Approval and authorization solve different problems" title="Direct link to Approval and authorization solve different problems" translate="no">​</a></h2>
<p>A write capability can request AI SDK approval:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> updateSchoolContactPhone </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">defineTeaQLCapability</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'updateSchoolContactPhone'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  description</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'Update one school contact phone with an explicit audit reason.'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  inputSchema</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">object</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    schoolId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">number</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">positive</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    contactPhone</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">min</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">max</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    auditReason</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> z</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">min</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">max</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">200</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  risk</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'write'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  needsApproval</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">execute</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> input </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> school </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">loadSchool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">schoolId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> school</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateContactPhone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">input</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">contactPhone</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">auditAs</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">input</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">auditReason</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Approval asks whether the user authorizes this proposed tool call.
Authorization asks whether the authenticated user is allowed to perform the
operation at all. Audit records what happened and why. Validation determines
whether the proposed state is legal.</p>
<p>These controls reinforce one another, but they are not interchangeable:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Agent proposes a write</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; AI SDK approval</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; TeaQL runtime authorization</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; domain validation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; audited save</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; persisted result</span><br></div></code></pre></div></div>
<p>A prompt that says "do not update restricted schools" is useful guidance. It
is not a runtime permission boundary.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="preserve-the-persisted-result">Preserve the persisted result<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#preserve-the-persisted-result" class="hash-link" aria-label="Direct link to Preserve the persisted result" title="Direct link to Preserve the persisted result" translate="no">​</a></h2>
<p>The included school example starts with a secondary school whose contact phone
is explicitly null and whose optimistic version is <code>1</code>. After an approved,
audited update, the tool returns the persisted object with the new phone and
version <code>2</code>:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Persisted result: {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  id: 1,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  name: 'Riverside Secondary School',</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  schoolType: 'SECONDARY',</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  contactPhone: '+1-555-0100',</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  version: 2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>Returning the authoritative persisted entity matters when a database assigns
an ID, a trigger or default supplies a value, or optimistic versioning changes
state. A write tool should not reconstruct a record from its input and pretend
that it represents the database result.</p>
<p>TeaQL also distinguishes loaded, explicit null, and not-loaded states. A
partially projected entity cannot safely collapse those states into ordinary
TypeScript <code>undefined</code> values.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="observe-failures-without-leaking-them">Observe failures without leaking them<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#observe-failures-without-leaking-them" class="hash-link" aria-label="Direct link to Observe failures without leaking them" title="Direct link to Observe failures without leaking them" translate="no">​</a></h2>
<p>Tool execution emits lifecycle events that can feed structured logs or an
OpenTelemetry adapter:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> tools </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createTeaQLTools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  capabilities</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">onEvent</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> event </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> telemetry</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">record</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The default events include capability name, risk, tool-call ID and timing.
Inputs are excluded because they may contain sensitive business data.</p>
<p>When capability execution fails, server telemetry receives the original error.
The model receives a safe message such as:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">The updateSchoolContactPhone business operation could not be completed.</span><br></div></code></pre></div></div>
<p>Applications can map public error messages, but raw connection strings, SQL,
credentials and internal exception details remain on the server.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="native-vercel-ai-sdk-integration">Native Vercel AI SDK integration<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#native-vercel-ai-sdk-integration" class="hash-link" aria-label="Direct link to Native Vercel AI SDK integration" title="Direct link to Native Vercel AI SDK integration" translate="no">​</a></h2>
<p>The resulting object is an AI SDK <code>ToolSet</code> and can be passed directly to an
agent:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> UserContext </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@teaql/teaql'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> ToolLoopAgent </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'ai'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> createTeaQLTools </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@teaql/ai-sdk'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> context </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">UserContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertResource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'schoolRepository'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> repository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> agent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ToolLoopAgent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  model</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'openai/gpt-5.4'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  instructions</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'Use only the provided business tools. Never invent SQL or database fields.'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  tools</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createTeaQLTools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    capabilities</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> schoolCapabilities</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The adapter uses AI SDK schemas, metadata, execution and approval semantics.
It does not require the application to adopt a second agent loop.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="run-the-demonstration-without-an-api-key">Run the demonstration without an API key<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#run-the-demonstration-without-an-api-key" class="hash-link" aria-label="Direct link to Run the demonstration without an API key" title="Direct link to Run the demonstration without an API key" translate="no">​</a></h2>
<p>The repository contains a deterministic school-management demonstration. It
uses in-memory SQLite, so no external database, model API key, or signup is
required:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">git clone https://github.com/teaql/teaql-ai-sdk.git</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">cd teaql-ai-sdk</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">npm install</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">npm run example</span><br></div></code></pre></div></div>
<p>The demonstration prints:</p>
<ul>
<li class="">the two model-visible capabilities;</li>
<li class="">approval metadata on the write tool;</li>
<li class="">schools whose contact value is explicitly null;</li>
<li class="">lifecycle events;</li>
<li class="">the persisted version change;</li>
<li class="">the audit record.</li>
</ul>
<p>The small SQLite repository is handwritten to keep the adapter demonstration
self-contained. In a generated TeaQL application, its implementation is
replaced by generated Q requests, entities, Save behavior and a Runtime Module.
The AI SDK adapter and its security boundary remain the same.</p>
<p>The package is published as
<a href="https://www.npmjs.com/package/@teaql/ai-sdk" target="_blank" rel="noopener noreferrer" class=""><code>@teaql/ai-sdk</code></a> and can be added
to an existing AI SDK application with:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npm install @teaql/ai-sdk @teaql/teaql ai zod</span><br></div></code></pre></div></div>
<p>The GitHub repository remains the source for the complete SQLite demonstration,
release workflow and implementation history.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="start-with-typescript-preserve-cross-runtime-semantics">Start with TypeScript, preserve cross-runtime semantics<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#start-with-typescript-preserve-cross-runtime-semantics" class="hash-link" aria-label="Direct link to Start with TypeScript, preserve cross-runtime semantics" title="Direct link to Start with TypeScript, preserve cross-runtime semantics" translate="no">​</a></h2>
<p>The initial adapter is TypeScript-first because the Vercel AI SDK is a
TypeScript ecosystem. TeaQL's larger responsibility is preserving one domain
language and equivalent runtime behavior across Java, Rust, TypeScript, Swift,
Python, .NET and Go.</p>
<p>The intended generation path is:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">TeaQL domain model</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; runtime entities and typed queries</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; explicit agent capability manifest</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; AI SDK tools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; MCP tools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; agent usage Markdown</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; executable TeaQL Agent Kit verification</span><br></div></code></pre></div></div>
<p>A TypeScript AI SDK application can execute capabilities locally through the
TeaQL TypeScript Runtime. The same capability manifest can later reach another
TeaQL runtime through MCP or the TeaQL Federal Protocol without teaching the
model seven unrelated database APIs.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-available-today">What is available today<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#what-is-available-today" class="hash-link" aria-label="Direct link to What is available today" title="Direct link to What is available today" translate="no">​</a></h2>
<p>The first public repository includes:</p>
<ul>
<li class="">native AI SDK <code>ToolSet</code> creation;</li>
<li class="">typed input and output schemas;</li>
<li class="">explicit capability and per-agent allowlists;</li>
<li class="">trusted server-side <code>UserContext</code> injection;</li>
<li class="">read, write and privileged risk metadata;</li>
<li class="">approval support;</li>
<li class="">safe error mapping;</li>
<li class="">lifecycle events for telemetry;</li>
<li class="">configuration validation;</li>
<li class="">five automated boundary tests;</li>
<li class="">a no-key SQLite demonstration;</li>
<li class="">a passing public GitHub Actions workflow.</li>
</ul>
<p>Generator-produced capability definitions, the hosted interactive demo,
OpenTelemetry export and cross-runtime MCP execution remain follow-up work. The
project documents those limits rather than presenting a thin adapter as a
finished enterprise security system.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it-and-challenge-the-boundary">Try it and challenge the boundary<a href="https://teaql.io/blog/safe-ai-sdk-tools-without-raw-sql#try-it-and-challenge-the-boundary" class="hash-link" aria-label="Direct link to Try it and challenge the boundary" title="Direct link to Try it and challenge the boundary" translate="no">​</a></h2>
<p>The most useful feedback is not whether another generic tool wrapper can be
added. It is whether the capability boundary remains understandable and
enforceable in a real application:</p>
<ul>
<li class="">Which business operations should become tools?</li>
<li class="">When should an operation require approval?</li>
<li class="">Which data must never appear in a model-visible schema or trace?</li>
<li class="">How should capability manifests evolve with a domain model?</li>
<li class="">Which negative conformance tests would make the security claim credible?</li>
</ul>
<p>The code, tests and runnable example are available at
<a href="https://github.com/teaql/teaql-ai-sdk" target="_blank" rel="noopener noreferrer" class=""><code>teaql/teaql-ai-sdk</code></a>. Related work is
maintained in the <a href="https://github.com/teaql/teaql-ts" target="_blank" rel="noopener noreferrer" class="">TeaQL TypeScript Runtime</a>,
<a href="https://github.com/teaql/teaql-agent-kit" target="_blank" rel="noopener noreferrer" class="">TeaQL Agent Kit</a>, and
<a href="https://github.com/teaql/teaql-conformance" target="_blank" rel="noopener noreferrer" class="">TeaQL Conformance</a>.</p>]]></content:encoded>
            <category>teaql</category>
            <category>typescript</category>
            <category>ai</category>
            <category>agents</category>
            <category>vercel-ai-sdk</category>
            <category>tool-calling</category>
            <category>security</category>
            <category>audit</category>
        </item>
        <item>
            <title><![CDATA[Internationalization as Application Infrastructure]]></title>
            <link>https://teaql.io/blog/internationalization-as-application-infrastructure</link>
            <guid>https://teaql.io/blog/internationalization-as-application-infrastructure</guid>
            <pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Why TeaQL is designing internationalization around UserContext, structured messages, six-runtime parity, and durable constraints for AI-assisted development.]]></description>
            <content:encoded><![CDATA[<p>Internationalization often enters an application as a small feature: read a language header, look up a string, and return the translated text. That approach works—until the application grows beyond one HTTP endpoint, one runtime, or one team.</p>
<p>TeaQL is taking a different path. We are designing internationalization as part of the application infrastructure: explicit in <code>UserContext</code>, structured before rendering, consistent across six programming languages, and constrained strongly enough that both people and coding agents can extend it without inventing a new architecture at every call site.</p>
<p>This work is still in design and is not yet a released portable TeaQL capability. This article explains why we believe the design is worth doing, the trade-offs we are making, and the kinds of organizations that benefit from it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-problem-is-not-translating-a-string">The problem is not translating a string<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#the-problem-is-not-translating-a-string" class="hash-link" aria-label="Direct link to The problem is not translating a string" title="Direct link to The problem is not translating a string" translate="no">​</a></h2>
<p>Mature applications execute work through many paths:</p>
<ul>
<li class="">an HTTP request;</li>
<li class="">a command-line tool;</li>
<li class="">a background job;</li>
<li class="">a message consumer;</li>
<li class="">a scheduled process;</li>
<li class="">a federated call between services;</li>
<li class="">a test or an AI-operated development harness.</li>
</ul>
<p>If each entry point discovers the locale independently, internationalization becomes transport-specific. The controller reads <code>Accept-Language</code>; the job uses an application default; a message consumer receives a language field; another service falls back to the operating system; and a test quietly depends on the developer's machine.</p>
<p>Every individual implementation may appear reasonable. Together they create several incompatible sources of truth.</p>
<p>The problem becomes more serious when an application returns only rendered text. Consider a validation failure reduced to this response:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"message"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"工作时长是必填项"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>The consumer can no longer reliably determine the error identity, affected field, typed arguments, or whether fallback occurred. Another API consumer cannot render it differently without parsing a sentence. Logs and tests become coupled to wording that translators should be free to improve.</p>
<p>The hard problem is therefore not string lookup. It is preserving meaning and context across the entire execution path.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-place-for-runtime-context">One place for runtime context<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#one-place-for-runtime-context" class="hash-link" aria-label="Direct link to One place for runtime context" title="Direct link to One place for runtime context" translate="no">​</a></h2>
<p>TeaQL already treats <code>UserContext</code> as the explicit carrier of runtime information. Internationalization should follow the same rule.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">application-specific inputs and override rules</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       initialize one UserContext</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> validation, translation, API output, jobs, and federation</span><br></div></code></pre></div></div>
<p>The logical internationalization state in <code>UserContext</code> separates two concerns:</p>
<ul>
<li class=""><code>LocalizationConfiguration</code> describes supported locales, defaults, fallback rules, catalogs, output mode, and safety policy.</li>
<li class=""><code>LocalizationPreference</code> describes the locale, time zone, currency, and formatting choices desired for the current execution.</li>
</ul>
<p>Configuration and preference are allowed to differ. Applications can replace either while initializing <code>UserContext</code>. A Web adapter might consider a validated request header; a background process might use a configured preference; a test might construct both directly. TeaQL does not prescribe one universal precedence algorithm for those application inputs.</p>
<p>After initialization, translation reads only <code>UserContext</code>. It does not query HTTP headers, authentication records, databases, thread-local state, or process defaults. It has no concept of the business source from which the application derived a preference.</p>
<p>This boundary costs a little convenience. Every execution path must propagate <code>UserContext</code> correctly. We accept that cost because explicit propagation is observable, testable, and portable across runtimes with very different concurrency models.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="preserve-meaning-before-rendering">Preserve meaning before rendering<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#preserve-meaning-before-rendering" class="hash-link" aria-label="Direct link to Preserve meaning before rendering" title="Direct link to Preserve meaning before rendering" translate="no">​</a></h2>
<p>TeaQL messages should remain structured until a deliberate rendering boundary. A validation result can retain:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"code"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"REQUIRED"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"path"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"timesheet"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"workedHour"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"message"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"key"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"validation.required"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"arguments"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"field"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"term"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"entity.Timesheet.field.workedHour"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>The stable code, key, field path, and typed argument names form the contract. Rendered text is a presentation derived from that contract.</p>
<p>This leads to three useful API modes:</p>
<ul>
<li class=""><code>STRUCTURED</code> lets a client or downstream service own rendering.</li>
<li class=""><code>RENDERED</code> serves consumers that want ready-to-display text while retaining stable identity.</li>
<li class=""><code>BOTH</code> carries the structured message and rendered result, which is useful for migration and diagnostics.</li>
</ul>
<p>The effective mode is also part of <code>UserContext</code>. An API adapter may map an explicitly allowed consumer preference into the context during initialization, but unrestricted dynamic input and ordinary federation payloads cannot rewrite the established policy.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="models-contain-language-sensitive-meaning">Models contain language-sensitive meaning<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#models-contain-language-sensitive-meaning" class="hash-link" aria-label="Direct link to Models contain language-sensitive meaning" title="Direct link to Models contain language-sensitive meaning" translate="no">​</a></h2>
<p>TeaQL is model-driven, so internationalization cannot stop at application error strings. The model contains entities, properties, relations, actions, and query predicates that users eventually see.</p>
<p>Generated descriptors can give these concepts stable identities without putting translated sentences into generated source files. Application catalogs can then override generated or framework text without being overwritten by regeneration.</p>
<p>Natural-language details matter here. Pluralization is not appending <code>s</code> or <code>es</code>. Human and non-human subjects may require different predicates. A plural human collection may read “Who are active?”, while an attributed predicate may use “Whose email is …”. These are language semantics, not naming shortcuts.</p>
<p>We want the generator to provide stable descriptors and reviewed grammatical intent. We want translators and mature localization engines to control the final sentence.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-teaql-should-ownand-what-it-should-not">What TeaQL should own—and what it should not<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#what-teaql-should-ownand-what-it-should-not" class="hash-link" aria-label="Direct link to What TeaQL should own—and what it should not" title="Direct link to What TeaQL should own—and what it should not" translate="no">​</a></h2>
<p>TeaQL should own the portable application contract:</p>
<ul>
<li class="">where localization state lives;</li>
<li class="">how configuration and preference are represented;</li>
<li class="">stable message and term identities;</li>
<li class="">typed arguments and field paths;</li>
<li class="">deterministic fallback and catalog precedence;</li>
<li class="">structured federation behavior;</li>
<li class="">observability and privacy rules;</li>
<li class="">the conformance corpus shared by all runtimes.</li>
</ul>
<p>TeaQL should not invent a new set of plural, date, number, currency, or grammatical rules. ICU, CLDR, Fluent, and mature language ecosystems already contain deep expertise in those areas. The portable TeaQL subset should be implemented on top of proven facilities where possible.</p>
<p>This division is important. A proprietary formatter would quickly diverge across Java, Rust, Go, Python, C#/.NET, and TypeScript. A shared semantic contract backed by established formatting engines gives us both portability and linguistic depth.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shared-runtimes-create-an-opportunity-for-shared-governance">Shared runtimes create an opportunity for shared governance<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#shared-runtimes-create-an-opportunity-for-shared-governance" class="hash-link" aria-label="Direct link to Shared runtimes create an opportunity for shared governance" title="Direct link to Shared runtimes create an opportunity for shared governance" translate="no">​</a></h2>
<p>Supporting six languages creates a problem if every runtime also creates an independent language site. An enterprise could end up translating the same entity, field, action, and validation concept six times—and still use different terminology in each product.</p>
<p>We see an opportunity to treat terminology as governed application metadata. A centralized TeaQL console can receive generated model descriptors and manage:</p>
<ul>
<li class="">stable identities and approved display names for domain concepts;</li>
<li class="">definitions and usage guidance for enterprise vocabulary;</li>
<li class="">human/non-human and other grammatical metadata;</li>
<li class="">locale variants and translator context;</li>
<li class="">ownership, review, approval, publication, and rollback;</li>
<li class="">catalog versions, hashes, and compatibility information;</li>
<li class="">conflicts, missing translations, and affected applications.</li>
</ul>
<p>The workflow becomes:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">models and application descriptors</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">central terminology and catalog console</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> author → review → approve → publish</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">versioned catalog snapshots</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Java · Rust · Go · Python · .NET · TypeScript</span><br></div></code></pre></div></div>
<p>This is more than centralized storage. It allows an organization to decide once what a business concept means and how it should be presented, then make that decision observable and consistent across language stacks. A terminology change has an owner, a review record, an immutable version, an impact report, and a rollback path.</p>
<p>The console is a control plane, not a synchronous dependency of every translation. Runtimes consume versioned, content-addressed catalog snapshots and select the active registry through <code>UserContext</code>. Applications remain available when the console is unavailable, and a rendered result can report exactly which catalog version produced it.</p>
<p>This separation preserves the runtime boundary: translation still knows only <code>UserContext</code> and published catalogs. It does not learn about the organizational systems that authored or approved them.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="six-languages-change-the-standard-of-correctness">Six languages change the standard of correctness<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#six-languages-change-the-standard-of-correctness" class="hash-link" aria-label="Direct link to Six languages change the standard of correctness" title="Direct link to Six languages change the standard of correctness" translate="no">​</a></h2>
<p>Implementing the feature in Java is not enough. TeaQL supports Java, Rust, Go, Python, C#/.NET, and TypeScript, and the same application meaning must survive all six.</p>
<p>We therefore plan one shared conformance corpus covering:</p>
<ul>
<li class="">locale normalization and deterministic fallback;</li>
<li class="">missing and malformed catalogs;</li>
<li class="">named and typed arguments;</li>
<li class="">plural, ordinal, selection, and term behavior;</li>
<li class="">numbers, dates, currencies, and time zones;</li>
<li class="">generated domain labels and validation paths;</li>
<li class="">human and non-human predicates;</li>
<li class="">catalog overrides and cache invalidation;</li>
<li class="">direct and federated parity;</li>
<li class="">trusted-context protection;</li>
<li class="">pseudolocalization and right-to-left text.</li>
</ul>
<p>The goal is not identical internal code. Each runtime should feel natural in its own language. The goal is identical observable semantics.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-makes-architectural-boundaries-more-important">AI makes architectural boundaries more important<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#ai-makes-architectural-boundaries-more-important" class="hash-link" aria-label="Direct link to AI makes architectural boundaries more important" title="Direct link to AI makes architectural boundaries more important" translate="no">​</a></h2>
<p>Coding agents are very good at extending a visible pattern. When no pattern is explicit, they are equally capable of creating locally convincing architecture drift.</p>
<p>An agent asked to localize one endpoint may read a header directly, add a <code>locale</code> parameter, translate an exception into a string, and use the machine default when no value is available. The change may pass its local test. Repeated across a codebase, it creates a system that nobody intentionally designed.</p>
<p>TeaQL's response is not to ask every agent to rediscover the architecture. The framework should make the safe path obvious and the wrong path difficult:</p>
<ol>
<li class="">Internationalization state belongs in <code>UserContext</code>.</li>
<li class="">Translation, validation, and execution do not gain a second locale or policy parameter.</li>
<li class="">Entry-point adapters initialize the same context contract.</li>
<li class="">Structured error identity is never replaced by localized prose.</li>
<li class="">Unsupported or forbidden input fails explicitly instead of selecting an accidental fallback.</li>
<li class="">Every runtime must pass the same portable fixtures.</li>
</ol>
<p>These constraints will eventually become maintained agent rules in the generator as well as runtime APIs and tests. Documentation explains the architecture; generated guidance puts it in front of coding agents; types and conformance tests enforce it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-this-matters-most">Where this matters most<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#where-this-matters-most" class="hash-link" aria-label="Direct link to Where this matters most" title="Direct link to Where this matters most" translate="no">​</a></h2>
<p>The clearest beneficiaries are organizations whose systems already span multiple languages and infrastructure generations. A core transaction platform may use Java, performance-sensitive services Rust, cloud services Go, AI workloads Python, internal enterprise systems .NET, and application edges TypeScript.</p>
<p>Without a shared contract, each ecosystem gradually develops its own interpretation of context, validation, errors, audit, pagination, and localization. The cost is not visible in the first service. It appears years later as duplicated platform work, inconsistent behavior, and migrations that cannot be verified.</p>
<p>For platform-engineering teams, TeaQL can provide a paved road that is broader than one framework template. Teams keep language-appropriate APIs while inheriting the same application guarantees. New languages and infrastructure can enter without resetting the organization's governance and semantics.</p>
<p>Long-lived software products also benefit. Their technology stacks rarely remain frozen for a decade. A stable, model-driven contract allows the product to evolve without turning each new runtime into an independent application platform.</p>
<p>This does not mean a new or single-language system has nothing to gain. Explicit context, structured errors, generated descriptors, deterministic behavior, and AI-oriented guardrails are valuable before a second language arrives. Such a system can start with one runtime while avoiding assumptions that make later growth expensive.</p>
<p>The primary value, however, becomes most visible when organizational and technical diversity are unavoidable: languages may differ, but application meaning should not.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-goal-is-durable-evolution">The goal is durable evolution<a href="https://teaql.io/blog/internationalization-as-application-infrastructure#the-goal-is-durable-evolution" class="hash-link" aria-label="Direct link to The goal is durable evolution" title="Direct link to The goal is durable evolution" translate="no">​</a></h2>
<p>TeaQL is not trying to become another translation-string library. We are designing a model-driven internationalization and context layer that can remain coherent across languages, execution paths, APIs, and coding agents.</p>
<p>That is a larger commitment than adding <code>translate(key)</code>. It requires a portable schema, runtime integrations, generated descriptors, federation rules, shared fixtures, and release evidence. It also gives us something much more durable: an application can evolve its languages, databases, frameworks, and infrastructure without allowing its meaning to fragment at the same rate.</p>
<p>The complete proposal is available in the <a class="" href="https://teaql.io/docs/core/core-concepts/internationalization-design">Internationalization Design Baseline</a>. The development warning will remain until the portable contract is implemented and verified across the supported runtimes.</p>]]></content:encoded>
            <category>teaql</category>
            <category>architecture</category>
            <category>internationalization</category>
            <category>ai</category>
            <category>polyglot</category>
        </item>
        <item>
            <title><![CDATA[TeaQL's TypeScript Runtime Is Now Available on npm]]></title>
            <link>https://teaql.io/blog/teaql-typescript-runtime-on-npm</link>
            <guid>https://teaql.io/blog/teaql-typescript-runtime-on-npm</guid>
            <pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Install the first public TeaQL TypeScript runtime release from npm, with SQL adapters for PostgreSQL, MySQL, and SQLite.]]></description>
            <content:encoded><![CDATA[<p>TeaQL's TypeScript runtime is now publicly available as
<a href="https://www.npmjs.com/package/@teaql/teaql" target="_blank" rel="noopener noreferrer" class=""><code>@teaql/teaql</code></a>. The first release,
<code>0.1.0</code>, can be installed directly from npm:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npm install @teaql/teaql</span><br></div></code></pre></div></div>
<p>The package contains the core runtime and explicit SQL entry points for PostgreSQL, MySQL, and
SQLite. Install only the database driver your application uses:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">npm install @teaql/teaql pg pg-query-stream       # PostgreSQL</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">npm install @teaql/teaql mysql2                    # MySQL</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">npm install @teaql/teaql better-sqlite3            # SQLite</span><br></div></code></pre></div></div>
<p>The published artifact was built and tested with Node.js 22. We also installed it from the public
registry into a clean project and loaded the main, SQL core, PostgreSQL, MySQL, and SQLite exports.</p>
<p>This release makes the same runtime used by TeaQL's generated TypeScript applications available
through the standard Node.js package workflow. Source, issues, and release development remain in
the <a href="https://github.com/teaql/teaql-ts" target="_blank" rel="noopener noreferrer" class=""><code>teaql-ts</code></a> repository.</p>
<p>Future releases are configured to publish from GitHub Actions through npm Trusted Publishing,
using short-lived OIDC credentials instead of a stored long-lived npm publishing token.</p>]]></content:encoded>
            <category>teaql</category>
            <category>typescript</category>
            <category>nodejs</category>
            <category>npm</category>
            <category>postgresql</category>
            <category>mysql</category>
            <category>sqlite</category>
        </item>
        <item>
            <title><![CDATA[Who Are Active? Human and Non-human Predicates in Generated Query APIs]]></title>
            <link>https://teaql.io/blog/human-nonhuman-query-predicates</link>
            <guid>https://teaql.io/blog/human-nonhuman-query-predicates</guid>
            <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How TeaQL keeps human and non-human query vocabulary consistent across six generated languages.]]></description>
            <content:encoded><![CDATA[<p>Generated query APIs contain language, not only identifiers. That makes a small grammatical choice
part of the public contract.</p>
<p>For a collection of people, TeaQL uses <code>whoAreActive()</code>, not <code>whoIsActive()</code>. For an ordinary human
attribute it uses <code>whoseEmailIs(...)</code>. A non-human entity uses <code>whichAreActive()</code> and
<code>withCodeIs(...)</code>.</p>
<p>These forms sound related, but they solve different problems: <code>whose</code> expresses possession, while
<code>who are</code> agrees with the plural result set.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="humanity-must-be-declared">Humanity must be declared<a href="https://teaql.io/blog/human-nonhuman-query-predicates#humanity-must-be-declared" class="hash-link" aria-label="Direct link to Humanity must be declared" title="Direct link to Humanity must be declared" translate="no">​</a></h2>
<p>TeaQL classifies an entity as human only when the model explicitly declares <code>cat="human"</code>. The
generator does not infer it from names such as customer, user, employee or person.</p>
<p>This avoids cultural guesses and domain ambiguity. A <code>user</code> may be a service account; a <code>customer</code>
may be an organization. The model owns the semantic decision.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-vocabulary-six-casing-conventions">One vocabulary, six casing conventions<a href="https://teaql.io/blog/human-nonhuman-query-predicates#one-vocabulary-six-casing-conventions" class="hash-link" aria-label="Direct link to One vocabulary, six casing conventions" title="Direct link to One vocabulary, six casing conventions" translate="no">​</a></h2>
<p>Java generated Request APIs are the semantic gold standard. Other languages preserve the same
meaning and adapt casing only:</p>
<table><thead><tr><th>Predicate</th><th>Human</th><th>Non-human</th></tr></thead><tbody><tr><td>scalar field</td><td><code>whose&lt;Field&gt;...</code></td><td><code>with&lt;Field&gt;...</code></td></tr><tr><td>positive boolean</td><td><code>whoAre&lt;Field&gt;</code></td><td><code>whichAre&lt;Field&gt;</code></td></tr><tr><td>negative boolean</td><td><code>whoAreNot&lt;Field&gt;</code></td><td><code>whichAreNot&lt;Field&gt;</code></td></tr></tbody></table>
<p>Boolean fields should preferably be adjectives such as <code>active</code>. A field named <code>is_active</code> pushes
grammar into schema naming and tends to generate repeated <code>Is</code> fragments.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-this-needed-a-generator-level-test">Why this needed a generator-level test<a href="https://teaql.io/blog/human-nonhuman-query-predicates#why-this-needed-a-generator-level-test" class="hash-link" aria-label="Direct link to Why this needed a generator-level test" title="Direct link to Why this needed a generator-level test" translate="no">​</a></h2>
<p>Several target templates once hard-coded <code>with</code>, bypassing the human classification. Java also had
a remaining singular boolean form. Fixing examples would not have fixed generated APIs.</p>
<p>We centralized predicate naming and added paired fixtures: a human <code>person</code> and a non-human
<code>device</code>, both with equivalent string, scalar and boolean fields. The six-language test requires
forms equivalent to <code>whoseEmailIs</code>, <code>withCodeIs</code>, <code>whoAreActive</code>, <code>whoAreNotActive</code> and
<code>whichAreActive</code>, while rejecting <code>whoIsActive</code>.</p>
<p>The lasting rule is simple: semantic vocabulary comes from the model and generator core, never from
a target template's intuition.</p>]]></content:encoded>
            <category>teaql</category>
            <category>code-generation</category>
            <category>query-api</category>
            <category>java</category>
            <category>rust</category>
            <category>go</category>
            <category>python</category>
            <category>dotnet</category>
            <category>typescript</category>
        </item>
        <item>
            <title><![CDATA[Lightweight Skills, Strong Tools: A Practical Architecture for Reliable AI Agents]]></title>
            <link>https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents</link>
            <guid>https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents</guid>
            <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Why strong, model-aware tools—not ever-growing collections of Skills—should form the core of harness engineering for reliable AI agents.]]></description>
            <content:encoded><![CDATA[<p>As AI agents become more capable, it is tempting to make their Skills increasingly detailed. Every new failure becomes another instruction. Every exception becomes another paragraph. Eventually, the Skill tries to describe the domain, encode the workflow, enforce safety, teach the tool interface, and anticipate every future mistake.</p>
<p>That approach does not scale.</p>
<p>Our practical conclusion is different:</p>
<blockquote>
<p>Keep Skills lightweight. Make Tools strong.</p>
</blockquote>
<p>This is not an argument for fewer safeguards. It is an argument about where safeguards belong.</p>
<p>It is also a principle for <strong>harness engineering</strong>. The core of an agent harness should not be an ever-growing library of Skills. It should be a set of strong, model-aware Tools and deterministic feedback loops that turn guidance into enforceable action boundaries.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-vehicle-analogy">The Vehicle Analogy<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#the-vehicle-analogy" class="hash-link" aria-label="Direct link to The Vehicle Analogy" title="Direct link to The Vehicle Analogy" translate="no">​</a></h2>
<p>An AI agent can be understood as a vehicle operating in the real world:</p>
<ol>
<li class=""><strong>The large language model is the engine.</strong> It supplies the general power to understand language, reason, plan, and generate possible actions.</li>
<li class=""><strong>Skills are the traffic rules.</strong> They prescribe how the agent should conduct itself: which procedures to follow, when to inspect or yield, what evidence is required, and which actions are prohibited.</li>
<li class=""><strong>Tools are the steering wheel and brakes.</strong> They determine where the agent can actually direct its power, which actions it can execute, and where execution must stop.</li>
<li class=""><strong>The world model is the map.</strong> It describes which places exist, how they are connected, which routes are possible, and how the reachable world changes over time.</li>
</ol>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Agent vehicle</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Engine              = LLM</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Traffic rules       = Skills</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Steering and brakes = Tools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Map                 = World Model</span><br></div></code></pre></div></div>
<p>An engine can produce motion, but it cannot define the world, choose a valid route, or stop itself safely. Traffic rules can guide behavior, but prose alone cannot steer or brake the vehicle. A map can describe the available space, but it cannot execute an action.</p>
<p>Reliable agency emerges only when these four responsibilities remain distinct and work together.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-skills-should-stay-lightweight">Why Skills Should Stay Lightweight<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#why-skills-should-stay-lightweight" class="hash-link" aria-label="Direct link to Why Skills Should Stay Lightweight" title="Direct link to Why Skills Should Stay Lightweight" translate="no">​</a></h2>
<p>A Skill should describe stable operating discipline:</p>
<ul>
<li class="">the objective of the workflow;</li>
<li class="">the stages the agent should follow;</li>
<li class="">when it should inspect, evaluate, repair, or escalate;</li>
<li class="">which evidence is required before declaring success;</li>
<li class="">how feedback should influence the next step.</li>
</ul>
<p>It should not try to become a second implementation of every system it uses.</p>
<p>When detailed domain rules are copied into Skill prose, several problems appear:</p>
<ul>
<li class="">the instructions become too large to load and apply consistently;</li>
<li class="">the same rule exists in both prose and executable software;</li>
<li class="">documentation and runtime behavior drift apart;</li>
<li class="">failures lead to more prompt patches rather than better system boundaries;</li>
<li class="">compliance depends on the model remembering an instruction at the right moment.</li>
</ul>
<p>Adding more Skills introduces a second problem: context competition. Each Skill consumes context, introduces terminology, and adds rules that the model must retrieve and reconcile during the task. As the collection grows, relevant instructions compete with irrelevant ones, overlapping Skills may disagree, and the agent has less attention available for the actual state of the problem.</p>
<p>More importantly, Skills are text. They can influence behavior, but they cannot guarantee behavior. An agent may misunderstand a rule, apply it at the wrong time, lose it in a long context, or choose a plausible action that the Skill never anticipated. No amount of prose can ensure complete compliance from a probabilistic model.</p>
<p>If a rule must always hold, it cannot live only in a Skill.</p>
<p>Traffic rules should be clear and economical. They should not attempt to reproduce the engine, the controls, or the map.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-makes-a-tool-strong">What Makes a Tool Strong<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#what-makes-a-tool-strong" class="hash-link" aria-label="Direct link to What Makes a Tool Strong" title="Direct link to What Makes a Tool Strong" translate="no">​</a></h2>
<p>A strong Tool is not a large Tool, and a strong toolset is not necessarily a large collection of Tools.</p>
<p>A Tool is strong when it exposes a narrow, semantically meaningful operation with:</p>
<ul>
<li class="">explicit inputs and outputs;</li>
<li class="">clear authority and permission boundaries;</li>
<li class="">known side effects;</li>
<li class="">deterministic validation where possible;</li>
<li class="">actionable failure feedback;</li>
<li class="">audit evidence and provenance;</li>
<li class="">traceability from intent to result.</li>
</ul>
<p>The steering-wheel part directs power toward a valid action. The brake part prevents or rejects an invalid action. Both are necessary.</p>
<p>A generic execution shell may be powerful, but it provides little semantic steering. A domain-aware operation such as <code>evaluate model</code>, <code>approve payment</code>, or <code>generate from accepted specification</code> offers a much stronger control surface. It tells the agent what kind of action exists, what it requires, and how success or failure will be judged.</p>
<p>The strongest Tool does not merely execute what the model asks. It helps constrain the space of askable actions.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="strong-tools-are-the-core-of-harness-engineering">Strong Tools Are the Core of Harness Engineering<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#strong-tools-are-the-core-of-harness-engineering" class="hash-link" aria-label="Direct link to Strong Tools Are the Core of Harness Engineering" title="Direct link to Strong Tools Are the Core of Harness Engineering" translate="no">​</a></h2>
<p>An agent harness is the engineered environment around the model. It determines what context is supplied, what actions are available, how actions are validated, what feedback is returned, and what evidence is required before work is considered complete.</p>
<p>In that environment, Skills are useful—but they are not the enforcement layer. They provide compact procedural guidance. The core control surface is the Tool layer.</p>
<p>A strong harness moves critical behavior out of optional textual compliance and into executable structure:</p>
<ul>
<li class="">schemas reject malformed inputs;</li>
<li class="">permissions prevent unauthorized actions;</li>
<li class="">domain Tools expose valid operations instead of raw implementation access;</li>
<li class="">evaluators reject invalid models and explain why;</li>
<li class="">generated APIs prevent the agent from inventing interfaces;</li>
<li class="">state machines disallow invalid transitions;</li>
<li class="">compilers and tests reject inconsistent implementations;</li>
<li class="">runtime guards enforce policies at the moment of execution;</li>
<li class="">audit trails record what happened and why.</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Skill</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  suggests the procedure</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Agent</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  reasons and proposes an action</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Strong Tool</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  constrains, validates, executes, or stops</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Harness Feedback</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  returns evidence for the next reasoning step</span><br></div></code></pre></div></div>
<p>This is the essential difference between instructions and a harness. An instruction says, “Do not cross this boundary.” A harness makes the boundary difficult or impossible to cross, detects the attempt, and returns structured feedback.</p>
<p>The goal is not to eliminate agent judgment. It is to focus that judgment where semantics are genuinely uncertain while moving mechanical correctness into deterministic controls.</p>
<p>For that reason, harness engineering should prioritize better Tools over more Skills. When a failure repeats, the durable fix is usually not another paragraph. It is a narrower interface, a stronger validator, a clearer state model, a permission boundary, or a better feedback signal.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-world-model-defines-the-reachable-space">The World Model Defines the Reachable Space<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#the-world-model-defines-the-reachable-space" class="hash-link" aria-label="Direct link to The World Model Defines the Reachable Space" title="Direct link to The World Model Defines the Reachable Space" translate="no">​</a></h2>
<p>Tools determine how an agent acts, but the world model determines what the agent believes it can act upon.</p>
<p>A useful world model explains:</p>
<ul>
<li class="">which concepts exist;</li>
<li class="">which relationships connect them;</li>
<li class="">which events can change those relationships;</li>
<li class="">which constraints make an event or state valid;</li>
<li class="">which states are currently reachable;</li>
<li class="">what would change if a proposed action occurred.</li>
</ul>
<p>Without that map, an agent may operate its controls correctly and still drive toward an invented destination. It may call a valid API while misunderstanding the meaning of the entity, role, state, or transition behind it.</p>
<p>The world model therefore limits and explains the action space. It gives both Skills and Tools a shared semantic reference.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="from-probabilistic-understanding-to-deterministic-results">From Probabilistic Understanding to Deterministic Results<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#from-probabilistic-understanding-to-deterministic-results" class="hash-link" aria-label="Direct link to From Probabilistic Understanding to Deterministic Results" title="Direct link to From Probabilistic Understanding to Deterministic Results" translate="no">​</a></h2>
<p>LLM reasoning is probabilistic. That does not mean the resulting software process must be probabilistic from end to end.</p>
<p>A more reliable workflow is:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Human Intent</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Model</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Deterministic Evaluation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Repair</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Deterministic Generation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Constrained Customization</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Verification</span><br></div></code></pre></div></div>
<p>The model is audited before it becomes executable. Errors are returned as structured feedback. The agent repairs the model and submits it again. Once accepted, deterministic generation projects that model into code and model-aware APIs. Later customization occurs through those constrained interfaces and is checked again by compilers, tests, policies, and runtime guards.</p>
<p>This creates an important separation:</p>
<ul>
<li class="">AI interprets intent and proposes semantic changes;</li>
<li class="">the harness supplies the relevant context and available action space;</li>
<li class="">deterministic Tools evaluate, generate, constrain, and verify;</li>
<li class="">the accepted model remains the traceable source of meaning.</li>
</ul>
<p>The result is not code that merely happened to be produced by an AI. It is a deterministic artifact derived from an audited semantic model, followed by customization inside explicit boundaries.</p>
<p>Our work with TeaQL was one practical source of this conclusion: repeated model evaluation and repair produced deterministic generated code and a constrained path for subsequent customization.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="feedback-belongs-in-the-system">Feedback Belongs in the System<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#feedback-belongs-in-the-system" class="hash-link" aria-label="Direct link to Feedback Belongs in the System" title="Direct link to Feedback Belongs in the System" translate="no">​</a></h2>
<p>When an agent makes a mistake, the default response should not always be to add another sentence to its Skill.</p>
<p>First ask where the missing knowledge or enforcement belongs:</p>
<ul>
<li class="">If it is stable operating guidance, improve the Skill.</li>
<li class="">If it defines the domain, improve the world model.</li>
<li class="">If it controls what can be executed, improve the Tool.</li>
<li class="">If it is mechanically verifiable, improve the evaluator, compiler, test, policy, or runtime guard.</li>
</ul>
<p>This turns failure into system improvement instead of prompt accumulation.</p>
<p>The feedback loop becomes:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Attempt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Tool Feedback</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Model or Implementation Repair</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Re-evaluation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  -&gt; Verified Result</span><br></div></code></pre></div></div>
<p>The agent still reasons and adapts, but it does not carry the entire burden of correctness in its context window.</p>
<p>This is how the harness becomes more capable without becoming a larger prompt: repeated failures improve the executable environment rather than permanently expanding the text the agent must remember.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-better-division-of-responsibility">A Better Division of Responsibility<a href="https://teaql.io/blog/lightweight-skills-strong-tools-reliable-ai-agents#a-better-division-of-responsibility" class="hash-link" aria-label="Direct link to A Better Division of Responsibility" title="Direct link to A Better Division of Responsibility" translate="no">​</a></h2>
<p>The architecture can be summarized in four lines:</p>
<blockquote>
<p>The LLM provides the power.<br>
<!-- -->Skills define the rules of conduct.<br>
<!-- -->Tools provide steering and braking.<br>
<!-- -->The world model defines the reachable world.</p>
</blockquote>
<p>“Lightweight Skills, Strong Tools” is therefore not primarily a prompt-writing technique. It is the central design principle of a reliable agent harness.</p>
<p>Reliable agents will not come from developing more and more Skills and asking a language model to remember them all. They will come from combining capable models with concise operating rules, explicit maps of reality, and a strong harness whose Tools make valid actions controllable, invalid actions stoppable, and every consequential result verifiable.</p>]]></content:encoded>
            <category>ai</category>
            <category>agents</category>
            <category>agent-skill</category>
            <category>tools</category>
            <category>harness-engineering</category>
            <category>architecture</category>
        </item>
        <item>
            <title><![CDATA[Pluralization Is Not `name + s`: A Code Generator Maintenance Rule]]></title>
            <link>https://teaql.io/blog/pluralization-is-not-append-s</link>
            <guid>https://teaql.io/blog/pluralization-is-not-append-s</guid>
            <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Why TeaQL centralizes plural names instead of letting six language templates guess English suffixes.]]></description>
            <content:encoded><![CDATA[<p>One of the smallest code generator shortcuts creates one of the most persistent API defects:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">plural = name + "s"</span><br></div></code></pre></div></div>
<p>It works for <code>order</code>, which makes it look harmless. Then it produces <code>order_statuss</code>, <code>categorys</code>,
<code>persons</code>, <code>childs</code>, and <code>inventorys</code>.</p>
<p>During TeaQL's six-language acceptance work, we found this assumption in Python and Go query
templates and in a Rust diagnostic. The generated code compiled often enough for the mistake to
survive until an entity ending in <code>status</code> exposed it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-rule-belongs-above-the-templates">The rule belongs above the templates<a href="https://teaql.io/blog/pluralization-is-not-append-s#the-rule-belongs-above-the-templates" class="hash-link" aria-label="Direct link to The rule belongs above the templates" title="Direct link to The rule belongs above the templates" translate="no">​</a></h2>
<p>TeaQL now treats plural names as generator metadata. Templates consume a centralized plural name
and only transform its casing for the target language. They may not append <code>s</code> or <code>es</code> themselves.</p>
<p>That rule covers more than query entry points. It also applies to relation collections, sample-data
methods, documentation examples, AI-assist prompts and diagnostics. Otherwise the generated API and
the instructions used to call it eventually disagree.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="an-inflection-library-is-a-component-not-the-contract">An inflection library is a component, not the contract<a href="https://teaql.io/blog/pluralization-is-not-append-s#an-inflection-library-is-a-component-not-the-contract" class="hash-link" aria-label="Direct link to An inflection library is a component, not the contract" title="Direct link to An inflection library is a component, not the contract" translate="no">​</a></h2>
<p>A library can handle common suffix rules but still choose a technically defensible word that is
wrong for the public API. In our tests, the inflector returned <code>persons</code>; the TeaQL collection
contract requires <code>people</code>.</p>
<p>The centralized policy therefore includes conventional irregular mappings and compound suffix
replacement:</p>
<table><thead><tr><th>Singular</th><th>Required plural</th></tr></thead><tbody><tr><td><code>order_status</code></td><td><code>order_statuses</code></td></tr><tr><td><code>category</code></td><td><code>categories</code></td></tr><tr><td><code>person</code></td><td><code>people</code></td></tr><tr><td><code>sales_person</code></td><td><code>sales_people</code></td></tr><tr><td><code>child</code></td><td><code>children</code></td></tr><tr><td><code>inventory</code></td><td><code>inventory</code></td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="regeneration-is-the-compatibility-strategy">Regeneration is the compatibility strategy<a href="https://teaql.io/blog/pluralization-is-not-append-s#regeneration-is-the-compatibility-strategy" class="hash-link" aria-label="Direct link to Regeneration is the compatibility strategy" title="Direct link to Regeneration is the compatibility strategy" translate="no">​</a></h2>
<p>We did not retain wrong names as aliases. Generated APIs are cheap to regenerate, while every
compatibility alias becomes a permanent maintenance and documentation cost.</p>
<p>The regression suite now generates regular, suffix-changing, irregular, compound and uncountable
fixtures. It checks the current Java, Rust, Go, Python, .NET and TypeScript output instead of testing
the pluralizer in isolation.</p>
<p>The lesson is broader than English grammar: templates should render reviewed naming decisions, not
make linguistic decisions independently.</p>]]></content:encoded>
            <category>teaql</category>
            <category>code-generation</category>
            <category>java</category>
            <category>rust</category>
            <category>go</category>
            <category>python</category>
            <category>dotnet</category>
            <category>typescript</category>
            <category>api-design</category>
        </item>
        <item>
            <title><![CDATA[252 Dynamic Queries Later: TeaQL's Six-Language Order Search Acceptance]]></title>
            <link>https://teaql.io/blog/polyglot-order-search-acceptance</link>
            <guid>https://teaql.io/blog/polyglot-order-search-acceptance</guid>
            <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The final TeaQL Order Search matrix: six languages, three core databases, seven extended Feature passes, dual audit paths, and real TypeScript-to-Rust federation.]]></description>
            <content:encoded><![CDATA[<p>On August 12 we published a persistence baseline across six TeaQL runtimes and a nine-database Java
matrix. That was useful evidence, but it was not the complete Order Search Feature.</p>
<p>The next acceptance run closed that distinction. Java, Rust, Go, Python, .NET and TypeScript each
executed the generated Order Search API against PostgreSQL, MySQL and SQLite: <strong>18 of 18 core cells
passed</strong>, representing <strong>252 successful positive dynamic scenario executions</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-a-complete-core-cell-proved">What a complete core cell proved<a href="https://teaql.io/blog/polyglot-order-search-acceptance#what-a-complete-core-cell-proved" class="hash-link" aria-label="Direct link to What a complete core cell proved" title="Direct link to What a complete core cell proved" translate="no">​</a></h2>
<p>Each language/database cell executed empty, root, parent, child, range, combined, empty-result and
stable-pagination queries plus an exact per-parent Top-N. Rows, record count, SUM and grouped facets
shared the same active filter and used database-native COUNT, SUM and GROUP BY.</p>
<p>Top-N evidence showed a partition/window plan rather than application overfetch. Preset saves were
tenant-scoped, audited, idempotent and versioned; stale versions were rejected. Purpose, comment and
audit-reason gates were exercised through the real generated APIs.</p>
<table><thead><tr><th>Language</th><th>PostgreSQL</th><th>MySQL</th><th>SQLite</th></tr></thead><tbody><tr><td>Java</td><td>PASS</td><td>PASS</td><td>PASS</td></tr><tr><td>Rust</td><td>PASS</td><td>PASS</td><td>PASS</td></tr><tr><td>Go</td><td>PASS</td><td>PASS</td><td>PASS</td></tr><tr><td>Python</td><td>PASS</td><td>PASS</td><td>PASS</td></tr><tr><td>.NET</td><td>PASS</td><td>PASS</td><td>PASS</td></tr><tr><td>TypeScript</td><td>PASS</td><td>PASS</td><td>PASS</td></tr></tbody></table>
<p>Unknown fields, trusted-context override attempts, reversed ranges, wrong types, excessive IN/page
size, deep paths, forbidden sorts and illegal offsets were rejected by the shared trusted endpoint
validator before query construction. We report that boundary accurately rather than pretending each
rejection was a language-specific SQL execution.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="governance-was-part-of-pass">Governance was part of PASS<a href="https://teaql.io/blog/polyglot-order-search-acceptance#governance-was-part-of-pass" class="hash-link" aria-label="Direct link to Governance was part of PASS" title="Direct link to Governance was part of PASS" translate="no">​</a></h2>
<p>All six runtimes now expose two distinct mutation audit paths:</p>
<ol>
<li class="">a server-owned row or mutation audit path;</li>
<li class="">a separately attributable application audit sink receiving metadata-masked events.</li>
</ol>
<p>The 18 core cells passed both paths. Application feature logging was not accepted as a substitute
for runtime audit infrastructure.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="extended-databases-moved-beyond-persistence-only">Extended databases moved beyond persistence-only<a href="https://teaql.io/blog/polyglot-order-search-acceptance#extended-databases-moved-beyond-persistence-only" class="hash-link" aria-label="Direct link to Extended databases moved beyond persistence-only" title="Direct link to Extended databases moved beyond persistence-only" translate="no">​</a></h2>
<p>Java completed the full Feature on Oracle, DB2, DM8, SAP HANA, SQL Server and DuckDB. .NET completed
the same Feature on SQL Server. These seven results cover stable pages, tenant isolation, exact
Top-N, complete child counts, native aggregates, preset persistence, optimistic locking and
governance—not only create/save/reconnect tests.</p>
<p>Snowflake remains <code>BLOCKED_BY_ENVIRONMENT</code> because the test environment lacks a complete account and
authenticated user/context profile. A token alone was not treated as a connection profile, and no
PASS was invented.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="federation-used-the-real-protocol">Federation used the real protocol<a href="https://teaql.io/blog/polyglot-order-search-acceptance#federation-used-the-real-protocol" class="hash-link" aria-label="Direct link to Federation used the real protocol" title="Direct link to Federation used the real protocol" translate="no">​</a></h2>
<p>The generated TypeScript client sent its query through TeaQL's Federal Protocol <code>/query</code> endpoint.
The Rust server routed it through <code>teaql-tfp-endpoint</code> to the PostgreSQL-backed generated runtime.
Direct Rust and federated responses had identical canonical IDs.</p>
<p>Client attempts to override tenant, merchant, user, permissions, request policy, purpose policy and
trusted context were rejected. A generic HTTP wrapper was not counted as federation.</p>
<p>The result is intentionally scoped: every executable core and extended cell passed, while global
status remains a GAP until Snowflake has a complete external connection environment. Evidence is
valuable only when its boundary is as precise as its green cells.</p>]]></content:encoded>
            <category>teaql</category>
            <category>database</category>
            <category>testing</category>
            <category>java</category>
            <category>rust</category>
            <category>go</category>
            <category>python</category>
            <category>dotnet</category>
            <category>typescript</category>
            <category>federation</category>
            <category>audit</category>
        </item>
        <item>
            <title><![CDATA[Six Languages, One Query Meaning: Closing TeaQL API Parity Gaps]]></title>
            <link>https://teaql.io/blog/six-language-api-parity</link>
            <guid>https://teaql.io/blog/six-language-api-parity</guid>
            <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[What it took to align naming, expressions, loaded state, query intent, and generated compilation across six TeaQL runtimes.]]></description>
            <content:encoded><![CDATA[<p>“Supports six languages” should mean more than producing six directories that compile. The same
model must preserve the same query meaning, loaded-state behavior and governance boundaries in every
generated API.</p>
<p>TeaQL recently used Java's generated Request API as the semantic reference and ran paired generation
tests across Rust, Go, Python, .NET and TypeScript. The work exposed gaps that ordinary runtime unit
tests had missed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-parity-contract">The parity contract<a href="https://teaql.io/blog/six-language-api-parity#the-parity-contract" class="hash-link" aria-label="Direct link to The parity contract" title="Direct link to The parity contract" translate="no">​</a></h2>
<p>The final generator enforces these shared invariants:</p>
<ul>
<li class="">plural names come from centralized naming metadata;</li>
<li class="">human classification comes only from explicit model metadata;</li>
<li class="">human predicates use <code>whose</code> and <code>whoAre</code>; non-human predicates use <code>with</code> and <code>whichAre</code>;</li>
<li class="">execution receives only UserContext and becomes available after purpose;</li>
<li class="">expression facades distinguish loaded null from not loaded;</li>
<li class="">known-wrong generated names are corrected, not retained as aliases.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="expressions-revealed-deeper-differences">Expressions revealed deeper differences<a href="https://teaql.io/blog/six-language-api-parity#expressions-revealed-deeper-differences" class="hash-link" aria-label="Direct link to Expressions revealed deeper differences" title="Direct link to Expressions revealed deeper differences" translate="no">​</a></h2>
<p>Python lacked its generated <code>E</code> expression facade. Go needed both an <code>E</code> facade and loaded-state
support. Without that state, a null database value and a field that was never selected can collapse
into the same representation.</p>
<p>The generated expression tests now cover scalar values, relation IDs, null, not-loaded, fallback,
list size and list traversal. This matters for dynamic projections and partial entity loading, where
an absent column must not masquerade as a business null.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="compile-the-generated-result">Compile the generated result<a href="https://teaql.io/blog/six-language-api-parity#compile-the-generated-result" class="hash-link" aria-label="Direct link to Compile the generated result" title="Direct link to Compile the generated result" translate="no">​</a></h2>
<p>Template assertions are useful but insufficient. The parity suite generates paired human and
non-human models, inspects the actual public API, then compiles fresh workspaces against the current
formal runtimes.</p>
<p>The final matrix passed Java gold-standard generation, six-language predicate parity,
pluralization regression, TypeScript/Python/Rust/.NET generated compile-and-run checks, and Go
generated compilation plus SQLite persistence and expression checks.</p>
<p>Cross-language consistency is not achieved by making every language look syntactically identical.
It comes from centralizing semantic decisions and verifying each language's real generated surface.</p>]]></content:encoded>
            <category>teaql</category>
            <category>code-generation</category>
            <category>java</category>
            <category>rust</category>
            <category>go</category>
            <category>python</category>
            <category>dotnet</category>
            <category>typescript</category>
            <category>testing</category>
        </item>
        <item>
            <title><![CDATA[One Execution Argument: Why TeaQL Queries Receive Only UserContext]]></title>
            <link>https://teaql.io/blog/user-context-only-execution</link>
            <guid>https://teaql.io/blog/user-context-only-execution</guid>
            <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[TeaQL's six generated runtimes resolve providers, identity, policy, and services from trusted UserContext initialization.]]></description>
            <content:encoded><![CDATA[<p>A generated TeaQL query has exactly one caller-supplied runtime dependency argument:
<code>UserContext</code>.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">execute_for_list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>There is no second data-service, provider or connection argument. Those dependencies—together with
tenant identity, authenticated user, permissions and policy—are installed when the trusted context
is initialized and resolved from it during execution.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-a-second-argument-is-structurally-wrong">Why a second argument is structurally wrong<a href="https://teaql.io/blog/user-context-only-execution#why-a-second-argument-is-structurally-wrong" class="hash-link" aria-label="Direct link to Why a second argument is structurally wrong" title="Direct link to Why a second argument is structurally wrong" translate="no">​</a></h2>
<p>An API such as <code>execute_for_list(ctx, service)</code> creates two possible sources of runtime truth. The
context may authorize one tenant while the separately supplied service points somewhere else. Even
when today's implementation is safe, the shape invites future bypasses and inconsistent tests.</p>
<p>TeaQL therefore applies the context-only rule to list, one, entity-list, entity-one and mutation
operations across Java, Rust, Go, Python, .NET and TypeScript. Required resources fail closed when
context initialization omitted them.</p>
<p>An audit reason remains an explicit business intent value. It is not dependency injection.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="purpose-is-a-type-state-transition">Purpose is a type-state transition<a href="https://teaql.io/blog/user-context-only-execution#purpose-is-a-type-state-transition" class="hash-link" aria-label="Direct link to Purpose is a type-state transition" title="Direct link to Purpose is a type-state transition" translate="no">​</a></h2>
<p>Comment and purpose have different roles:</p>
<ul>
<li class="">comment describes what operation is being performed and may appear anywhere in the builder chain;</li>
<li class="">purpose explains why the application needs the read;</li>
<li class="">after purpose, the Request transitions into an executable state.</li>
</ul>
<p>A canonical flow is:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Q.orders()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  .comment("Find orders awaiting review")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  ...filters, sorting, selections...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  .purpose("Prepare the authorized review queue")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  .executeForList(ctx)</span><br></div></code></pre></div></div>
<p>Comment does not have to sit immediately before purpose. The important design constraint is that
execution is not exposed before purpose.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cross-language-verification">Cross-language verification<a href="https://teaql.io/blog/user-context-only-execution#cross-language-verification" class="hash-link" aria-label="Direct link to Cross-language verification" title="Direct link to Cross-language verification" translate="no">​</a></h2>
<p>The acceptance work removed obsolete Python and .NET two-argument forms and added required-resource
resolution to generated runtimes. Tests cover successful injection, missing-resource failure and
rejection of the old call shape. Freshly generated workspaces compile and execute with their formal
runtimes.</p>
<p>This is an API-design control, not merely a runtime <code>if</code> statement: make the unsafe call difficult
or impossible to express.</p>]]></content:encoded>
            <category>teaql</category>
            <category>api-design</category>
            <category>security</category>
            <category>multi-tenancy</category>
            <category>java</category>
            <category>rust</category>
            <category>go</category>
            <category>python</category>
            <category>dotnet</category>
            <category>typescript</category>
        </item>
        <item>
            <title><![CDATA[.NET Nullable Is Not Load State: Preserving SQL NULL in E Expressions]]></title>
            <link>https://teaql.io/blog/dotnet-nullable-is-not-load-state</link>
            <guid>https://teaql.io/blog/dotnet-nullable-is-not-load-state</guid>
            <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[TeaQL .NET keeps loaded nulls distinct from unselected fields across ADO.NET, generated records, typed entities, and E-expression evaluation.]]></description>
            <content:encoded><![CDATA[<p>C# nullable reference types answer an important question: may this property have
no value?</p>
<p>They do not answer a different data-access question: was this property loaded
at all?</p>
<p>For a partially selected entity, <code>string? Name == null</code> can mean either SQL NULL
or “the query never selected Name.” TeaQL's generated .NET E expressions model
those as separate states and preserve the distinction through ADO.NET mapping.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-nullable-types-are-necessary-but-insufficient">Why Nullable Types Are Necessary but Insufficient<a href="https://teaql.io/blog/dotnet-nullable-is-not-load-state#why-nullable-types-are-necessary-but-insufficient" class="hash-link" aria-label="Direct link to Why Nullable Types Are Necessary but Insufficient" title="Direct link to Why Nullable Types Are Necessary but Insufficient" translate="no">​</a></h2>
<p>Suppose a task name is optional:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">string? name = E.Task(task).Name().Eval();</span><br></div></code></pre></div></div>
<p>If the query selected <code>name</code> and the database returned NULL, <code>Eval()</code> should
return <code>null</code>. If the query selected only <code>id</code>, the same return value would hide
an incomplete query.</p>
<p>The generated contract is:</p>
<table><thead><tr><th>State</th><th>Meaning</th><th>.NET behavior</th></tr></thead><tbody><tr><td>Value</td><td>Selected and non-null</td><td><code>Eval()</code> returns the value</td></tr><tr><td>Null</td><td>Selected and <code>DBNull</code></td><td><code>Eval()</code> returns <code>null</code></td></tr><tr><td>NotLoaded</td><td>Column absent from the row</td><td>throws <code>TeaQLNotLoadedException</code></td></tr></tbody></table>
<p><code>HasValue</code> also throws for NotLoaded. It cannot be used to turn a query error
into ordinary absence.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-adonet-boundary-matters">The ADO.NET Boundary Matters<a href="https://teaql.io/blog/dotnet-nullable-is-not-load-state#the-adonet-boundary-matters" class="hash-link" aria-label="Direct link to The ADO.NET Boundary Matters" title="Direct link to The ADO.NET Boundary Matters" translate="no">​</a></h2>
<p>Many row mappers contain logic like this:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">if (!reader.IsDBNull(index))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    record[reader.GetName(index)] = ConvertValue(reader.GetValue(index));</span><br></div></code></pre></div></div>
<p>That code destroys the distinction before the entity exists. A selected NULL
column disappears from the record and becomes indistinguishable from an
unselected column.</p>
<p>TeaQL now keeps the key and records an explicit null value:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">record[reader.GetName(index)] = reader.IsDBNull(index)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ? new Value.NullValue()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    : FromDbValue(reader.GetValue(index));</span><br></div></code></pre></div></div>
<p>The generated model then maps the record while retaining its keys:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Task task = Task.FromRecord(record);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">if (!task.IsLoaded("Name"))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    throw new Exception("Name should have been part of the projection");</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">string? name = E.Task(task).Name().Eval();</span><br></div></code></pre></div></div>
<p><code>FromRecord</code> assigns non-null values and marks every returned column as loaded,
including <code>Value.NullValue</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="typed-query-apis-for-e-evaluation">Typed Query APIs for E Evaluation<a href="https://teaql.io/blog/dotnet-nullable-is-not-load-state#typed-query-apis-for-e-evaluation" class="hash-link" aria-label="Direct link to Typed Query APIs for E Evaluation" title="Direct link to Typed Query APIs for E Evaluation" translate="no">​</a></h2>
<p>Generated requests expose raw records for aggregation and low-level work, and
typed entity methods for load-aware evaluation:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">var tasks = await Q.Tasks()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    .WithNameIs("Hello")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    .Comment("Read the task for display")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    .Purpose("Render the task detail page")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    .ExecuteEntitiesForListAsync(ctx, service);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">var name = E.Task(tasks[0]).Name().Eval();</span><br></div></code></pre></div></div>
<p>The corresponding single-result method is <code>ExecuteEntityForOneAsync</code>.</p>
<p>These APIs make the mapping choice explicit. A caller that wants dictionaries
can keep using <code>ExecuteForListAsync</code>; a caller that wants generated E expressions
can request load-aware models.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fallback-is-not-an-error-handler">Fallback Is Not an Error Handler<a href="https://teaql.io/blog/dotnet-nullable-is-not-load-state#fallback-is-not-an-error-handler" class="hash-link" aria-label="Direct link to Fallback Is Not an Error Handler" title="Direct link to Fallback Is Not an Error Handler" translate="no">​</a></h2>
<p>The following code uses a valid business default only when Name was loaded and
absent:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">string label = E.Task(task).Name().OrElse("Unnamed");</span><br></div></code></pre></div></div>
<p>For an unselected Name, <code>OrElse</code> propagates <code>TeaQLNotLoadedException</code>. The
exception includes <code>Root</code>, <code>AccessPath</code>, <code>BreakPoint</code>, and <code>SuggestedFix</code>:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">try</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    E.Task(Task.Refer(99)).Name().OrElse("Unnamed");</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">catch (TeaQLNotLoadedException error)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Console.WriteLine(error.AccessPath);   // Name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Console.WriteLine(error.SuggestedFix); // SelectName(...)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>This turns a silent default into an actionable test failure.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="real-sqlite-verification">Real SQLite Verification<a href="https://teaql.io/blog/dotnet-nullable-is-not-load-state#real-sqlite-verification" class="hash-link" aria-label="Direct link to Real SQLite Verification" title="Direct link to Real SQLite Verification" translate="no">​</a></h2>
<p>The generated .NET SQLite integration test creates and saves a task graph,
updates a selected column to SQL NULL through ADO.NET, reloads it with a typed
request, and verifies all three conditions:</p>
<div class="language-csharp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-csharp codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">typedLog.IsLoaded("Detail") == true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">E.TaskExecutionLog(typedLog).Detail().Eval() == null</span><br></div></code></pre></div></div>
<p>The same test also verifies schema creation, graph persistence, reconnect and
query, update, optimistic version increment, and direct database reads.</p>
<p>At the generator level, the full regression finished with 109 tests, zero
failures, and zero errors. Tests requiring unavailable connection variables
were reported as conditional skips rather than successes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="clear-failures-are-an-ai-feature">Clear Failures Are an AI Feature<a href="https://teaql.io/blog/dotnet-nullable-is-not-load-state#clear-failures-are-an-ai-feature" class="hash-link" aria-label="Direct link to Clear Failures Are an AI Feature" title="Direct link to Clear Failures Are an AI Feature" translate="no">​</a></h2>
<p>A coding agent faced with a late <code>NullReferenceException</code> must infer whether the
problem is bad data, a nullable field, mapping code, or a missing selection.</p>
<p>A <code>TeaQLNotLoadedException</code> reduces the repair to a bounded task: inspect the
generated request, add the exact selection identified by the diagnostic, and
rerun the test. The test then permanently verifies that the business expression
has the data it requires.</p>
<p>Nullable annotations describe the domain. Load state describes the query. A
robust data runtime needs both.</p>]]></content:encoded>
            <category>teaql</category>
            <category>dotnet</category>
            <category>csharp</category>
            <category>ado-net</category>
            <category>testing</category>
            <category>ai-native</category>
        </item>
        <item>
            <title><![CDATA[Dynamic Search Is Not One WHERE Clause: TeaQL vs Conventional Rust]]></title>
            <link>https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust</link>
            <guid>https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust</guid>
            <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[An evidence-driven order-page comparison that counts dynamic filters, strong results, facets, context, and review surface—not only SQL text.]]></description>
            <content:encoded><![CDATA[<p>A dynamic order page sounds ordinary: search, paginate, show status cards, and
preview a few products. The interesting part begins when we ask what a
production-grade implementation must actually contain—and count all of it.</p>
<p>We built the same read model with TeaQL Rust and conventional Rust plus SQLite.
The first comparison was wrong in three important ways. Correcting those errors
made the result more useful than the original benchmark.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-page-we-measured">The Page We Measured<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#the-page-we-measured" class="hash-link" aria-label="Direct link to The Page We Measured" title="Direct link to The Page We Measured" translate="no">​</a></h2>
<p>The page is an order management center with the following backend behavior:</p>
<ul>
<li class="">dynamically filter orders using fields selected at runtime;</li>
<li class="">support root fields, parent-relation paths, and child-relation paths;</li>
<li class="">return a stable paginated order list and the complete matching count;</li>
<li class="">calculate four status facets from the same active filter;</li>
<li class="">include order number, order date, status, and product previews;</li>
<li class="">include the complete line-item count for a <code>+N more</code> UI;</li>
<li class="">execute through a user context with an explicit business purpose;</li>
<li class="">leave SQL, result, elapsed-time, user, and purpose evidence;</li>
<li class="">return a typed native result rather than assembling unvalidated JSON.</li>
</ul>
<p>Both implementations used the same deterministic SQLite fixture. The verified
dataset contains 60 orders, evenly distributed across four statuses.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-the-first-comparison-was-wrong">Why the First Comparison Was Wrong<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#why-the-first-comparison-was-wrong" class="hash-link" aria-label="Direct link to Why the First Comparison Was Wrong" title="Direct link to Why the First Comparison Was Wrong" translate="no">​</a></h2>
<p>Benchmarks become persuasive by removing advantages, not by adding them. We
changed the comparison three times after reviewing its assumptions.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="correction-1-conventional-json-is-not-a-production-result">Correction 1: Conventional JSON Is Not a Production Result<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#correction-1-conventional-json-is-not-a-production-result" class="hash-link" aria-label="Direct link to Correction 1: Conventional JSON Is Not a Production Result" title="Direct link to Correction 1: Conventional JSON Is Not a Production Result" translate="no">​</a></h3>
<p>The first conventional implementation created <code>serde_json::Value</code> objects
inside SQLite row callbacks. It was executable, but it had no strong result
types, status enum, repository boundary, checked conversions, or structured
error model.</p>
<p>That understated the conventional implementation. We replaced it with a strong
<code>OrderPage</code> result containing typed rows, product previews, status facets,
dates, counts, and validation. We also added a repository boundary, request
context, purpose-aware SQL evidence, result summaries, and elapsed time.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="correction-2-the-domain-model-is-not-a-page-cost">Correction 2: The Domain Model Is Not a Page Cost<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#correction-2-the-domain-model-is-not-a-page-cost" class="hash-link" aria-label="Direct link to Correction 2: The Domain Model Is Not a Page Cost" title="Direct link to Correction 2: The Domain Model Is Not a Page Cost" translate="no">​</a></h3>
<p>TeaQL's 74-line model is excluded from the comparison.</p>
<p>That model is not disposable code written only for this page. Without TeaQL,
the same domain still needs to be described in requirements, an ER model,
schemas, API documentation, entities, or another durable specification. With
TeaQL, the model is also reused to generate APIs, documentation, runtime
metadata, and implementations in multiple languages.</p>
<p>Charging the whole model to one TeaQL page would count a reusable architectural
asset as a one-off feature cost.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="correction-3-teaql-does-not-need-a-handwritten-presenter">Correction 3: TeaQL Does Not Need a Handwritten Presenter<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#correction-3-teaql-does-not-need-a-handwritten-presenter" class="hash-link" aria-label="Direct link to Correction 3: TeaQL Does Not Need a Handwritten Presenter" title="Direct link to Correction 3: TeaQL Does Not Need a Handwritten Presenter" translate="no">​</a></h3>
<p>We initially wrote a 96-line Presenter that converted generated TeaQL entities
into the conventional <code>OrderPage</code> shape. That made byte-for-byte response
comparison easy, but it forced TeaQL to pay for an abstraction required only by
the conventional implementation.</p>
<p>The TeaQL runtime already serializes a generated <code>SmartList&lt;T&gt;</code> directly:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> page </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">load_order_page</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> response </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">WebResponse</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from_smart_list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">page</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>The Presenter was deleted. TeaQL now returns its native generated entity graph,
record count, dynamic aggregates, and facets. Conventional Rust returns its
handwritten strong <code>OrderPage</code>.</p>
<p>The two native wire shapes are intentionally allowed to differ. A test-only jq
normalizer extracts the business fields needed for semantic parity. That
normalizer is evidence tooling, not application code, and is excluded from both
sides.</p>
<p>This correction also changed the contract accounting. Only the 79-line input
request contract is shared and excluded. The 100-line conventional result
contract is now counted only on the conventional side.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-teaql-query">The TeaQL Query<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#the-teaql-query" class="hash-link" aria-label="Direct link to The TeaQL Query" title="Direct link to The TeaQL Query" translate="no">​</a></h2>
<p>The measured TeaQL data-access implementation is 31 nonblank handwritten lines:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">line_items_for_present</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">OrderLineRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">order_lines_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Select product previews for each order"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_product_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_image_url</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">order_statuses_for_facet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">OrderStatusRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">order_statuses_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_code</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">count_customer_orders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">load_order_page</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ctx</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token class-name">ServiceRuntime</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    request</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token class-name">OrderPageRequest</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">SmartList</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">CustomerOrder</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Box</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">dyn</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">error</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Error</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> filter_json </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">serde_json</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">to_string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">customer_orders_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Load the searchable order management page"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_order_number</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_order_date</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_status_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">order_statuses_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_code</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter_with_json</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">filter_json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">facet_by_status_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"order_status"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">order_statuses_for_facet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_order_line_list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">line_items_for_present</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">count_order_lines</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">order_by_order_number_asc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">purpose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Render the order management center"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute_for_page</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">offset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>This is not a string wrapper around one SQL statement. It asks for a typed
domain result with a relation, relation aggregate, total count, facet, dynamic
filter, stable order, paging, trace comments, and an execution purpose.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="composition-is-the-feature">Composition Is the Feature<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#composition-is-the-feature" class="hash-link" aria-label="Direct link to Composition Is the Feature" title="Direct link to Composition Is the Feature" translate="no">​</a></h2>
<p>Extracting <code>order_statuses_for_facet()</code> is more than a cosmetic refactor. The
function returns an <code>OrderStatusRequest</code>: a typed query value that can be passed
into the outer <code>CustomerOrderRequest</code>.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">order_statuses_for_facet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">OrderStatusRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">order_statuses_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_code</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">count_customer_orders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">customer_orders_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">facet_by_status_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"order_status"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">order_statuses_for_facet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>The same pattern composes the product-preview request into the order request:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_order_line_list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">line_items_for_present</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>This is a structural difference from ordinary handwritten SQL. SQL itself has
subqueries and CTEs, but application-level SQL fragments are usually not closed
under composition: two fragments can each be valid and still become invalid or
semantically wrong when concatenated. They may introduce a second <code>WHERE</code>,
reuse an alias or parameter position, change grouping, apply pagination at the
wrong level, or cause the list, count, and facet paths to disagree.</p>
<p>Conventional code can build a composable query AST to solve this problem, but
then the application or framework must provide typed nodes, relation metadata,
alias management, parameter binding, aggregate semantics, and a SQL compiler.
TeaQL generates that infrastructure from the domain model. The handwritten
unit of reuse is therefore a domain query—not a string fragment—and invalid
combinations are constrained by generated method signatures and the Rust type
checker before SQL is produced.</p>
<p>That is why naming a subquery as a function works so naturally here. The
function can be read, tested, reused, and nested without exposing SQL assembly
details to the page query.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dynamic-search-is-the-expensive-part">Dynamic Search Is the Expensive Part<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#dynamic-search-is-the-expensive-part" class="hash-link" aria-label="Direct link to Dynamic Search Is the Expensive Part" title="Direct link to Dynamic Search Is the Expensive Part" translate="no">​</a></h2>
<p>The verified input may choose any subset of six representative fields:</p>
<table><thead><tr><th>Path type</th><th>Searchable fields</th></tr></thead><tbody><tr><td>Root</td><td><code>order_number</code>, <code>order_date</code></td></tr><tr><td>Parent relation</td><td><code>status.code</code>, <code>status.name</code>, <code>customer.name</code></td></tr><tr><td>Child relation</td><td><code>order_line_list.product_name</code></td></tr></tbody></table>
<p>For example:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"order_date"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2024-01-2"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"status.code"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"PEND"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"order_line_list.product_name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Box"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>The generated TeaQL request layer resolves those paths from the domain model.
The query above does not change when the caller selects A, B, C, or A+B+C.</p>
<p>The conventional fixed-whitelist implementation must explicitly repeat the
mapping in the list, count, and facet queries:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">?</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">OR</span><span class="token plain"> o</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">order_number </span><span class="token operator" style="color:#393A34">LIKE</span><span class="token plain"> ?</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">?</span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">OR</span><span class="token plain"> o</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">order_date </span><span class="token operator" style="color:#393A34">LIKE</span><span class="token plain"> ?</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">?</span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">OR</span><span class="token plain"> s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">code </span><span class="token operator" style="color:#393A34">LIKE</span><span class="token plain"> ?</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">?</span><span class="token number" style="color:#36acaa">4</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">OR</span><span class="token plain"> s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">LIKE</span><span class="token plain"> ?</span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">?</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">OR</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">EXISTS</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> customer_data c</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> o</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">customer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">version </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">LIKE</span><span class="token plain"> ?</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">?</span><span class="token number" style="color:#36acaa">6</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">IS</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">OR</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">EXISTS</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">SELECT</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">FROM</span><span class="token plain"> order_line_data f</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">WHERE</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">customer_order </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> o</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">version </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token operator" style="color:#393A34">AND</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">product_name </span><span class="token operator" style="color:#393A34">LIKE</span><span class="token plain"> ?</span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>It must also keep parameter positions and typed values aligned across all three
statements.</p>
<p>There is another legitimate conventional design: build a generic search AST,
field registry, relation-path resolver, operator parser, type converter, and SQL
compiler. That avoids repeated fixed SQL, but it is no longer a small page
implementation. It is the beginning of model-driven query infrastructure.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-was-executed">What Was Executed<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#what-was-executed" class="hash-link" aria-label="Direct link to What Was Executed" title="Direct link to What Was Executed" translate="no">​</a></h2>
<p>The acceptance harness ran seven scenarios:</p>
<table><thead><tr><th>Scenario</th><th style="text-align:right">Matching orders</th><th style="text-align:right">Semantic diff</th></tr></thead><tbody><tr><td>Empty filter</td><td style="text-align:right">60</td><td style="text-align:right">0 bytes</td></tr><tr><td>Order number</td><td style="text-align:right">11</td><td style="text-align:right">0 bytes</td></tr><tr><td>Status code</td><td style="text-align:right">15</td><td style="text-align:right">0 bytes</td></tr><tr><td>Order date</td><td style="text-align:right">5</td><td style="text-align:right">0 bytes</td></tr><tr><td>Status name</td><td style="text-align:right">15</td><td style="text-align:right">0 bytes</td></tr><tr><td>Child product name</td><td style="text-align:right">11</td><td style="text-align:right">0 bytes</td></tr><tr><td>Date + status + child product</td><td style="text-align:right">2</td><td style="text-align:right">0 bytes</td></tr></tbody></table>
<p>Each semantic comparison covered rows, total count, line-item count, product
preview data, remaining count, and all four status facets.</p>
<p>The harness also proved that:</p>
<ul>
<li class="">both typed input boundaries reject unknown fields;</li>
<li class="">omitting TeaQL <code>.purpose(...)</code> causes a Rust compile error before execution;</li>
<li class="">the standard TeaQL log buffer records user, purpose, nested trace, SQL,
result summary, and elapsed time without feature-specific log statements;</li>
<li class="">the verified TeaQL trace contains no product-master N+1 query.</li>
</ul>
<p>TeaQL emitted seven SQL statements while the conventional implementation
emitted three. That is runtime evidence, not a performance score. The benchmark
does not claim that more or fewer statements alone predict latency, throughput,
or database cost.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="loc-is-only-half-the-review-cost">LOC Is Only Half the Review Cost<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#loc-is-only-half-the-review-cost" class="hash-link" aria-label="Direct link to LOC Is Only Half the Review Cost" title="Direct link to LOC Is Only Half the Review Cost" translate="no">​</a></h2>
<p>There is a second difference that a line-count table does not show: <strong>how many
places a reviewer must keep in working memory</strong>.</p>
<p>To review the business behavior of the TeaQL page, the reviewer opens one file:
<code>query.rs</code>. That file shows, in one continuous expression:</p>
<ul>
<li class="">which order fields are selected;</li>
<li class="">how status and line-item relations are projected;</li>
<li class="">where the dynamic filter enters;</li>
<li class="">how status facets and line-item counts are calculated;</li>
<li class="">how results are ordered and paginated;</li>
<li class="">the trace comments and the business purpose of execution.</li>
</ul>
<p>The generated model vocabulary, dynamic path resolution, typed result graph,
SQL generation, serialization, context propagation, and standard evidence do
not need to be reconstructed from page-specific glue code. The executable demo
also has a 25-line generic entry point, but it does not contain the page's
business query. For a change-focused review, the business review surface is one
file.</p>
<p>The conventional implementation is properly separated into layers, but a
complete feature review crosses five handwritten files:</p>
<table><thead><tr><th>File</th><th>What the reviewer must verify</th></tr></thead><tbody><tr><td>Result contract</td><td>Typed rows, facets, previews, validation, and wire shape</td></tr><tr><td><code>repository.rs</code></td><td>Dynamic-field mapping, three SQL paths, parameters, row mapping, and aggregation</td></tr><tr><td><code>context.rs</code></td><td>User, purpose, SQL trace, result summary, and elapsed time</td></tr><tr><td><code>error.rs</code></td><td>Database, conversion, validation, and unknown-field failures</td></tr><tr><td><code>main.rs</code></td><td>Assembly, execution, and serialization boundary</td></tr></tbody></table>
<p>This is not an argument against separation of concerns. Those separations are
necessary when the infrastructure is handwritten. It is an argument about
<strong>review fan-out</strong>: TeaQL keeps the page-specific decision in one declarative
query while generated and standard infrastructure carries the cross-cutting
concerns. Conventional Rust makes those responsibilities explicit in
application code, so the reviewer has to follow them across files and keep the
connections consistent.</p>
<p>For coding agents, this locality matters as much as raw LOC. A smaller diff is
useful; a diff whose meaning can be established from one file is easier to
generate, inspect, and revise.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-final-review-surface-numbers">The Final Review-Surface Numbers<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#the-final-review-surface-numbers" class="hash-link" aria-label="Direct link to The Final Review-Surface Numbers" title="Direct link to The Final Review-Surface Numbers" translate="no">​</a></h2>
<p>The primary comparison counts the handwritten data-access implementation:</p>
<table><thead><tr><th>Measured surface</th><th style="text-align:right">TeaQL</th><th style="text-align:right">Conventional Rust</th><th style="text-align:right">Reduction</th></tr></thead><tbody><tr><td>Data-access implementation</td><td style="text-align:right">31</td><td style="text-align:right">188</td><td style="text-align:right">83.5%</td></tr></tbody></table>
<p>The secondary comparison counts all handwritten runtime code used by the
executable benchmark:</p>
<table><thead><tr><th>TeaQL runtime surface</th><th style="text-align:right">LOC</th></tr></thead><tbody><tr><td>Query file</td><td style="text-align:right">36</td></tr><tr><td>Demo entry point with direct <code>WebResponse</code></td><td style="text-align:right">25</td></tr><tr><td><strong>Total</strong></td><td style="text-align:right"><strong>61</strong></td></tr></tbody></table>
<table><thead><tr><th>Conventional runtime surface</th><th style="text-align:right">LOC</th></tr></thead><tbody><tr><td>Strong result contract</td><td style="text-align:right">100</td></tr><tr><td>Request context and trace</td><td style="text-align:right">67</td></tr><tr><td>Error model</td><td style="text-align:right">45</td></tr><tr><td>Repository, SQL, and mapping</td><td style="text-align:right">211</td></tr><tr><td>Demo entry point</td><td style="text-align:right">20</td></tr><tr><td><strong>Total</strong></td><td style="text-align:right"><strong>443</strong></td></tr></tbody></table>
<p>That is 61 versus 443 nonblank handwritten lines, an 86.2% reduction in this
specific executable benchmark.</p>
<p>The following are excluded:</p>
<ul>
<li class="">the reusable domain model;</li>
<li class="">the shared input request contract;</li>
<li class="">generated TeaQL code;</li>
<li class="">fixture generation;</li>
<li class="">evidence exporters and semantic normalizers;</li>
<li class="">dependencies and build output;</li>
<li class="">blank lines and line comments.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-real-limitation-the-benchmark-foundand-the-fix-it-drove">A Real Limitation the Benchmark Found—and the Fix It Drove<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#a-real-limitation-the-benchmark-foundand-the-fix-it-drove" class="hash-link" aria-label="Direct link to A Real Limitation the Benchmark Found—and the Fix It Drove" title="Direct link to A Real Limitation the Benchmark Found—and the Fix It Drove" translate="no">​</a></h2>
<p>The benchmark exposed a correctness gap in TeaQL Rust 4.2.5: applying
<code>.limit(3)</code> to a nested relation limited the child query globally, rather than
selecting three children independently for every parent order.</p>
<p>That means the aesthetically ideal query:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token class-name">Q</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">order_lines_minimal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">limit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_product_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select_image_url</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>did <strong>not</strong> implement a per-order product preview correctly in the runtime used
for the original run. Keeping it in the benchmark would have made the TeaQL code
shorter but the result wrong, so the verified query did not use that limit.</p>
<p>Instead, the Rust response loads the order-line snapshots for the current page.
The test/UI projection consumes the first three children of each order while
the generated relation aggregate retains the complete line-item count. This
preserves the required response semantics, but it is bounded over-fetch—not the
ideal database execution plan.</p>
<p>A separate Java 1.526 probe generated the expected per-parent Top-N SQL using
<code>ROW_NUMBER() OVER (PARTITION BY customer_order ...)</code>. That probe also found a
different gap: its generated child-count value was not attached to the returned
parent entity.</p>
<p>The follow-up fix was implemented on 2026-08-12 against the TeaQL Rust v4.2.7
codebase. A paged relation request now carries its reverse foreign key as a
partition key. The SQL compiler emits <code>ROW_NUMBER() OVER (PARTITION BY ...)</code>,
applies offset and limit to each partition, and the runtime removes the internal
rank column before attaching children to their parents. The regression suite
checks two parents with three selected children each; a real in-memory SQLite
execution starts with five children for each parent and returns exactly six
rows, the top three per parent. The remote v4.2.7 run passed 171 Rust tests
across core, SQL, runtime, and the SQLite provider.</p>
<p>The Java child-count attachment path was fixed in the same follow-up. Its
portable SQL runtime now maps grouped aggregate rows back to the returned parent
entities, including a zero default when a parent has no matching child. The
remote Java reactor run passed 236 tests with no failures or errors.</p>
<p>These fixes close the two concrete parity gaps found by the probes. The original
benchmark evidence still records the behavior of the released runtime it
actually tested; its bounded-over-fetch implementation should remain in that
historical run until the complete benchmark is rerun against a release that
contains the Rust fix.</p>
<p>We publish this because a benchmark should be allowed to find defects in the
technology it evaluates. The limitation does not change the seven verified
semantic comparisons, dynamic-filter checks, purpose compile gate, trace
evidence, or review-surface measurement. It does narrow the performance claim:
this benchmark proves the behavior of the page, but it does not claim that the
Rust child-preview plan used in that original run was optimal.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-numbers-doand-do-notmean">What the Numbers Do—and Do Not—Mean<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#what-the-numbers-doand-do-notmean" class="hash-link" aria-label="Direct link to What the Numbers Do—and Do Not—Mean" title="Direct link to What the Numbers Do—and Do Not—Mean" translate="no">​</a></h2>
<p>This is not a universal claim that TeaQL is 83.5% shorter than every Rust data
stack. A framework with comparable model metadata and a dynamic query engine may
move much of the same work out of application code. That is precisely the
architectural point: the reduction comes from reusable infrastructure, not from
a clever spelling of SQL.</p>
<p>Handwritten SQL remains the right choice for one-off reporting, database-specific
optimization, or carefully tuned critical paths. The question is whether every
ordinary business page should manually rebuild field mapping, relation search,
counts, facets, typed assembly, context, and evidence.</p>
<p>Finally, fewer reviewed lines suggest fewer opportunities for coding-agent
drift and lower human review effort, but LOC is not a direct Token measurement.
We have not yet measured end-to-end model Token savings, so we do not convert
the LOC percentages into Token claims.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-this-matters-for-coding-agents">Why This Matters for Coding Agents<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#why-this-matters-for-coding-agents" class="hash-link" aria-label="Direct link to Why This Matters for Coding Agents" title="Direct link to Why This Matters for Coding Agents" translate="no">​</a></h2>
<p>A coding agent can generate 443 lines. The harder problem is keeping those
lines coherent when requirements change:</p>
<ul>
<li class="">a new searchable relationship is added;</li>
<li class="">a field changes type or name;</li>
<li class="">the list, count, and facet filters must remain identical;</li>
<li class="">user and purpose context must survive every execution path;</li>
<li class="">the response must remain typed and reviewable.</li>
</ul>
<p>TeaQL moves that repeated structure into a generated domain vocabulary and a
runtime query engine. The handwritten code stays close to the product manager's
language: orders, status, product previews, counts, filters, purpose, and page.</p>
<p>That is the more important result. The agent writes less code, but reviewers
also inspect code expressed in the same domain model used by the rest of the
system.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="source-and-related-reading">Source and Related Reading<a href="https://teaql.io/blog/dynamic-search-teaql-vs-conventional-rust#source-and-related-reading" class="hash-link" aria-label="Direct link to Source and Related Reading" title="Direct link to Source and Related Reading" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/teaql/goai-hangzhou-2026/tree/main/demo/order-read-model" target="_blank" rel="noopener noreferrer" class="">Order read-model benchmark source</a></li>
<li class=""><a class="" href="https://teaql.io/docs/cookbook/dynamic-json-query">Dynamic JSON Query cookbook</a></li>
<li class=""><a class="" href="https://teaql.io/blog/generated-query-apis-vs-handwritten-sql">Generated Query APIs vs Handwritten SQL</a></li>
<li class=""><a class="" href="https://teaql.io/blog/teaql-vs-mybatis-order-page-example">TeaQL vs MyBatis: an order page example</a></li>
</ul>
<p>The verified run recorded in the benchmark is
<code>named-status-facet-verified-20260812</code>. The evidence bundle contains native
responses, normalized semantic responses, parity diffs, SQL traces, the
missing-purpose compiler error, LOC measurement, and SHA-256 hashes.</p>]]></content:encoded>
            <category>teaql</category>
            <category>rust</category>
            <category>dynamic-search</category>
            <category>benchmark</category>
            <category>ai-coding</category>
        </item>
        <item>
            <title><![CDATA[Go E Expressions: Make Missing Preloads an Explicit Error]]></title>
            <link>https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit</link>
            <guid>https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit</guid>
            <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[TeaQL Go separates null-like absence from fields that were never loaded, with TryEval for explicit handling and fail-fast Eval for strict business logic.]]></description>
            <content:encoded><![CDATA[<p>Go programmers are comfortable with the comma-ok idiom:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ok </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">lookup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>That shape is useful for an E expression too, but one boolean cannot explain
<em>why</em> a value is absent. In data-access code, there is a critical difference
between a loaded null-like value and a field the query never selected.</p>
<p>TeaQL's generated Go E expressions preserve three states and provide two
evaluation styles: <code>TryEval()</code> for explicit error handling and <code>Eval()</code> for
strict fail-fast business logic.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-present--false-is-not-enough">When <code>present == false</code> Is Not Enough<a href="https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit#when-present--false-is-not-enough" class="hash-link" aria-label="Direct link to when-present--false-is-not-enough" title="Direct link to when-present--false-is-not-enough" translate="no">​</a></h2>
<p>This looks reasonable:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> present </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> E</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Task</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">task</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Eval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">present </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Unnamed"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>It is correct when <code>name</code> was loaded and legitimately absent. It is wrong when
the task came from an ID-only projection. In the latter case, the fallback
fabricates a business value from missing evidence.</p>
<p>TeaQL treats these cases differently:</p>
<table><thead><tr><th>State</th><th>Go result</th></tr></thead><tbody><tr><td>Value</td><td><code>(value, true, nil)</code> from <code>TryEval()</code></td></tr><tr><td>Null/missing path</td><td><code>(zeroValue, false, nil)</code></td></tr><tr><td>NotLoaded</td><td><code>(zeroValue, false, TeaQLNotLoadedError)</code></td></tr></tbody></table>
<p>The strict <code>Eval()</code> method has the familiar two-result shape, but panics if the
third state is NotLoaded.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="explicit-handling-with-tryeval">Explicit Handling with <code>TryEval</code><a href="https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit#explicit-handling-with-tryeval" class="hash-link" aria-label="Direct link to explicit-handling-with-tryeval" title="Direct link to explicit-handling-with-tryeval" translate="no">​</a></h2>
<p>At an application boundary, callers can inspect the error directly:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> present</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> E</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Task</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">task</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">TryEval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> notLoaded TeaQLNotLoadedError</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> errors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">As</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">err</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">notLoaded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> fmt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Errorf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"query did not load %s at %s: %w"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            notLoaded</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">BreakPoint</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            notLoaded</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">AccessPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            err</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> err</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">present </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Unnamed"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Inside invariant-heavy business logic, <code>Eval()</code> is intentionally stricter:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> present </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> E</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Task</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">task</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Eval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>If <code>Name</code> was not loaded, the panic contains the root entity, access path,
breakpoint, suggested selection, and a human-readable explanation.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fallback-does-not-hide-a-query-bug">Fallback Does Not Hide a Query Bug<a href="https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit#fallback-does-not-hide-a-query-bug" class="hash-link" aria-label="Direct link to Fallback Does Not Hide a Query Bug" title="Direct link to Fallback Does Not Hide a Query Bug" translate="no">​</a></h2>
<p>The generated <code>OrElse</code> operation first performs strict evaluation:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">label </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> E</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Task</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">task</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">OrElse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unnamed"</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>It returns the fallback only for a legitimate missing value. If the field was
not loaded, the same structured error propagates. This rule prevents a common
failure mode in which defensive code makes an incomplete query appear valid.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="load-state-comes-from-records">Load State Comes from Records<a href="https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit#load-state-comes-from-records" class="hash-link" aria-label="Direct link to Load State Comes from Records" title="Direct link to Load State Comes from Records" translate="no">​</a></h2>
<p>Generated Go entities record which keys were present when <code>FromRecord</code> mapped a
database or transport record:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">task </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> task</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">NewTask</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> task</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">FromRecord</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">record</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> err</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>A key present with a null-like database value is loaded. A key absent from the
record is NotLoaded. New entities are fully available for ordinary construction,
while <code>MarkLoadedOnly</code> supports precise partial-entity tests:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">partial </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> task</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">NewTask</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">UpdateId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">99</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">MarkLoadedOnly</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token boolean" style="color:#36acaa">_</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> E</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Task</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">partial</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">TryEval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Fatal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"expected an unloaded-field error"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>The same state is propagated through foreign-key ID accessors and generated
reverse-list expressions such as <code>Size</code>, <code>First</code>, and <code>Get</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-better-failure-for-humans-and-ai-agents">A Better Failure for Humans and AI Agents<a href="https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit#a-better-failure-for-humans-and-ai-agents" class="hash-link" aria-label="Direct link to A Better Failure for Humans and AI Agents" title="Direct link to A Better Failure for Humans and AI Agents" translate="no">​</a></h2>
<p>A generic panic such as <code>interface conversion: interface {} is nil</code> provides
almost no repair guidance. <code>TeaQLNotLoadedError</code> is a query-contract diagnostic:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">TeaQLNotLoadedError:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  root=Task(id=99)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  access_path=name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  break_point=name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  suggested_fix=SelectName(...)</span><br></div></code></pre></div></div>
<p>That structure matters during test-driven development. A developer immediately
knows which request to review. An AI coding agent can read the generated request
source, add the exact selection, and rerun the failing test without guessing a
method name.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="verification">Verification<a href="https://teaql.io/blog/go-e-expressions-make-missing-preloads-explicit#verification" class="hash-link" aria-label="Direct link to Verification" title="Direct link to Verification" translate="no">​</a></h2>
<p>The generated Go workspace was compiled and executed against the TeaQL Go
runtime used by the integration environment. Tests covered scalar evaluation,
foreign-key IDs, reverse-list traversal, <code>TryEval</code>, strict panic behavior, and
the rule that <code>OrElse</code> cannot hide NotLoaded.</p>
<p>The complete code-generator regression finished with 109 tests, zero failures,
and zero errors. Conditional tests that require additional database connection
variables remained skipped rather than being counted as passes.</p>
<p>Go's preference for explicit errors fits this design well. The important part
is not whether an application chooses <code>TryEval</code> or strict <code>Eval</code>; it is that the
runtime never collapses “we do not know” into “the value is empty.”</p>]]></content:encoded>
            <category>teaql</category>
            <category>go</category>
            <category>golang</category>
            <category>testing</category>
            <category>ai-native</category>
            <category>data-access</category>
        </item>
        <item>
            <title><![CDATA[Java E Expressions: Catch Unloaded Data Before Production]]></title>
            <link>https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests</link>
            <guid>https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests</guid>
            <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[TeaQL Java distinguishes loaded values, loaded nulls, and fields that were never selected—then turns preload mistakes into actionable test failures.]]></description>
            <content:encoded><![CDATA[<p>Java applications have spent decades improving null handling, yet one dangerous
ambiguity remains common in data-access code:</p>
<blockquote>
<p>Does <code>null</code> mean the database value is NULL, or does it mean the query never
loaded the property?</p>
</blockquote>
<p>Those two states have completely different business meanings. Treating both as
<code>null</code> can make a test pass and let the wrong decision reach production.</p>
<p>TeaQL's generated Java E expressions now preserve three states: <strong>Value</strong>,
<strong>Null</strong>, and <strong>NotLoaded</strong>. A missing preload becomes a structured exception at
the point of use, while a genuine SQL NULL remains a legitimate null value.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-bug-that-ordinary-null-safety-cannot-see">The Bug That Ordinary Null Safety Cannot See<a href="https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests#the-bug-that-ordinary-null-safety-cannot-see" class="hash-link" aria-label="Direct link to The Bug That Ordinary Null Safety Cannot See" title="Direct link to The Bug That Ordinary Null Safety Cannot See" translate="no">​</a></h2>
<p>Consider a task query that selects only <code>id</code>, followed by business logic that
reads <code>name</code>:</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Task partial = Task.refer(99L);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">String displayName = E.task(partial).getName().orElse("Unnamed");</span><br></div></code></pre></div></div>
<p>Returning <code>"Unnamed"</code> would look null-safe, but it would hide a query bug. The
application does not know that the name is absent; it never asked the database
for the name.</p>
<p>The generated E expression instead throws <code>E.TeaQLNotLoadedException</code>. Even the
fallback propagates the exception:</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">try {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    E.task(partial).getName().orElse("Unnamed");</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    throw new AssertionError("NotLoaded was hidden");</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">} catch (E.TeaQLNotLoadedException error) {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    assertEquals("name", error.getAccessPath());</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    assertEquals("name", error.getBreakPoint());</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    assertEquals("selectName(...)", error.getSuggestedFix());</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>This behavior is intentional. A default is appropriate for a loaded null, not
for missing evidence.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-three-state-contract">The Three-State Contract<a href="https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests#the-three-state-contract" class="hash-link" aria-label="Direct link to The Three-State Contract" title="Direct link to The Three-State Contract" translate="no">​</a></h2>
<p>The generated entity tracks which properties were loaded. E expressions carry
that state through scalar fields, to-one relations, and reverse lists.</p>
<table><thead><tr><th>State</th><th>Meaning</th><th>Java behavior</th></tr></thead><tbody><tr><td>Value</td><td>Selected and non-null</td><td><code>eval()</code> returns the value</td></tr><tr><td>Null</td><td>Selected and SQL NULL</td><td><code>eval()</code> returns <code>null</code></td></tr><tr><td>NotLoaded</td><td>Not selected by the query</td><td>throws <code>TeaQLNotLoadedException</code></td></tr></tbody></table>
<p>The distinction survives database mapping. TeaQL checks whether the result row
contains a column, not whether its value is non-null. A selected SQL NULL still
invokes the generated entity mapper and marks the property as loaded.</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Task loaded = /* loaded from a SELECT that includes name */;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">assertNull(E.task(loaded).getName().eval());</span><br></div></code></pre></div></div>
<p>That is a subtle but essential rule for partial projections and relation-heavy
domain models.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-diagnostic-designed-for-tests-and-coding-agents">A Diagnostic Designed for Tests and Coding Agents<a href="https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests#a-diagnostic-designed-for-tests-and-coding-agents" class="hash-link" aria-label="Direct link to A Diagnostic Designed for Tests and Coding Agents" title="Direct link to A Diagnostic Designed for Tests and Coding Agents" translate="no">​</a></h2>
<p>The exception includes machine-readable context:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">TeaQLNotLoadedError:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  root=Task(id=99)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  access_path=name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  break_point=name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  suggested_fix=selectName(...)</span><br></div></code></pre></div></div>
<p>For a deeper chain, the access path identifies the exact point where available
data ends. A developer can act on this immediately. An AI coding agent can do
the same without guessing method names or reconstructing the query from an
unrelated <code>NullPointerException</code>.</p>
<p>The resulting loop is short:</p>
<ol>
<li class="">Generate the typed model and query APIs.</li>
<li class="">Run unit or integration tests.</li>
<li class="">Let the E expression fail at the first unloaded access.</li>
<li class="">Read the path and suggested preload.</li>
<li class="">Update the generated query chain and rerun the test.</li>
</ol>
<p>The important shift is temporal: the bug becomes a test failure instead of a
production data-quality incident.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-this-is-more-than-another-optional-wrapper">Why This Is More Than Another Optional Wrapper<a href="https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests#why-this-is-more-than-another-optional-wrapper" class="hash-link" aria-label="Direct link to Why This Is More Than Another Optional Wrapper" title="Direct link to Why This Is More Than Another Optional Wrapper" translate="no">​</a></h2>
<p><code>Optional&lt;T&gt;</code> can represent a value or absence. It cannot, by itself, explain
whether absence is legitimate or caused by an incomplete query. Lazy-loading
proxies can defer the question, but they introduce hidden I/O and can still fail
after a session has closed.</p>
<p>E expressions make the query contract explicit. They do not issue a surprise
query. They either evaluate already-loaded data, return a legitimate null, or
identify the missing preload.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="verification-evidence">Verification Evidence<a href="https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests#verification-evidence" class="hash-link" aria-label="Direct link to Verification Evidence" title="Direct link to Verification Evidence" translate="no">​</a></h2>
<p>This behavior was tested in the generated Java code and in the Java runtime:</p>
<ul>
<li class="">a reference entity fails on an unloaded scalar, including through fallback;</li>
<li class="">PostgreSQL returns a genuine SQL NULL that evaluates as Null;</li>
<li class="">the portable SQL runtime maps a selected SQLite NULL as loaded;</li>
<li class="">the complete generator regression finished with 109 tests, zero failures,
and zero errors; environment-dependent database cases remained conditional.</li>
</ul>
<p>The PostgreSQL test ran against an isolated test container, and the portable
mapping test used a real in-memory SQLite database.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="an-ai-native-data-contract">An AI-Native Data Contract<a href="https://teaql.io/blog/java-e-expressions-catch-unloaded-data-in-tests#an-ai-native-data-contract" class="hash-link" aria-label="Direct link to An AI-Native Data Contract" title="Direct link to An AI-Native Data Contract" translate="no">​</a></h2>
<p>The goal is not to make every missing value fatal. The goal is to distinguish
business absence from missing information.</p>
<p>Once that distinction is part of generated code, tests become much more
powerful. They verify not only that a method returns the expected value, but
also that the query loaded enough evidence to make the decision. And when the
contract is violated, both humans and AI agents receive a precise repair path.</p>]]></content:encoded>
            <category>teaql</category>
            <category>java</category>
            <category>orm</category>
            <category>testing</category>
            <category>ai-native</category>
            <category>developer-experience</category>
        </item>
    </channel>
</rss>