<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Harshith Kala</title>
    <description>The latest articles on DEV Community by Harshith Kala (@harshith_kala).</description>
    <link>https://dev.to/harshith_kala</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4244878%2Fc5b99e98-f14f-4977-9d51-82872f5f914d.png</url>
      <title>DEV Community: Harshith Kala</title>
      <link>https://dev.to/harshith_kala</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshith_kala"/>
    <language>en</language>
    <item>
      <title>How I built a 3ms self-hosted AI drift proxy in Python (and wiped deleted prompts from SQLite WAL files)</title>
      <dc:creator>Harshith Kala</dc:creator>
      <pubDate>Sat, 14 Nov 2026 18:08:19 +0000</pubDate>
      <link>https://dev.to/harshith_kala/how-i-built-a-3ms-self-hosted-ai-drift-proxy-in-python-and-wiped-deleted-prompts-from-sqlite-wal-3aoh</link>
      <guid>https://dev.to/harshith_kala/how-i-built-a-3ms-self-hosted-ai-drift-proxy-in-python-and-wiped-deleted-prompts-from-sqlite-wal-3aoh</guid>
      <description>&lt;p&gt;If you run LLMs in production—whether OpenAI, Anthropic, Gemini, or self-hosted Ollama/vLLM—you have probably been burned by &lt;strong&gt;silent model drift&lt;/strong&gt;. An upstream provider tweaks quantization or safety filters overnight, refusal rates jump, or an update subtly breaks edge-case prompts without any announcement.&lt;/p&gt;

&lt;p&gt;Most observability platforms solve this in two frustrating ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They require shipping all your raw customer prompts to a third-party cloud.&lt;/li&gt;
&lt;li&gt;They rely on static threshold alerts (like alerting whenever response length changes), which spam false alarms whenever a model is naturally verbose.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Over the past few months (I’m 15, building on a basic setup with no GPU cluster or funding), I built &lt;strong&gt;&lt;a href="https://wallras.com" rel="noopener noreferrer"&gt;Wallras&lt;/a&gt;&lt;/strong&gt;—a single-container, self-hosted transparent proxy (&lt;code&gt;base_url&lt;/code&gt; swap, ~3–5ms overhead) that catches silent drift, model swaps, and confident hallucinations while keeping 100% of your data on your own servers.&lt;/p&gt;

&lt;p&gt;Here is a look under the hood at four engineering problems I had to solve while building it.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Replacing Naive Drift Thresholds With Permutation Math
&lt;/h3&gt;

&lt;p&gt;A static rule like &lt;em&gt;"alert if average response length shifts by 15%"&lt;/em&gt; breaks immediately on real traffic because some prompts naturally produce longer answers than others.&lt;/p&gt;

&lt;p&gt;Instead, Wallras combines three statistical signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Population Stability Index (PSI)&lt;/strong&gt; across response-length buckets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jensen-Shannon Divergence (JSD)&lt;/strong&gt; over the top 300 vocabulary tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two-Proportion Z-Tests&lt;/strong&gt; (&lt;code&gt;|z| &amp;gt; 3&lt;/code&gt;) for multilingual refusal-rate spikes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To avoid crying wolf, it runs &lt;strong&gt;150-iteration permutation shuffling&lt;/strong&gt; on baseline vs. recent outputs to measure that specific model's own natural random variance. It only raises a drift flag when a shift exceeds both a practical floor &lt;em&gt;and&lt;/em&gt; the model's 99th-percentile random noise ceiling (~1.7% false-alarm rate on noisy baselines).&lt;/p&gt;

&lt;p&gt;You can read the exact formulas and thresholds on the &lt;a href="https://wallras.com" rel="noopener noreferrer"&gt;measurement math page&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Catching "Confident Lies" via Logprob Entropy
&lt;/h3&gt;

&lt;p&gt;LLMs frequently sound 95% confident in plain English even when they are guessing a date, API parameter, or legal citation.&lt;/p&gt;

&lt;p&gt;When token logprobs are available (from OpenAI, OpenRouter, Ollama, or vLLM), Wallras computes Shannon entropy across the top alternative tokens alongside the geometric mean and minimum token probability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;internal_certainty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;geometric_mean_prob&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;min_token_prob&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Blending the average token probability with the &lt;strong&gt;single weakest token&lt;/strong&gt; ensures that one guessed fact buried inside an otherwise fluent paragraph still triggers a mismatch flag when the model's text sounds overly certain.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Forensic Deletion: Wiping SQLite WAL Files &amp;amp; Free Pages
&lt;/h3&gt;

&lt;p&gt;One of the trickiest security bugs I found during testing was with &lt;strong&gt;SQLite deletion requests&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a user triggers a GDPR deletion—or turns on field-level &lt;strong&gt;AES-256-GCM encryption&lt;/strong&gt; for existing records—running a standard SQL &lt;code&gt;DELETE&lt;/code&gt; or &lt;code&gt;UPDATE&lt;/code&gt; removes the row logically, &lt;strong&gt;but leaves the plaintext sitting inside SQLite's write-ahead log (&lt;code&gt;.wal&lt;/code&gt;) and unallocated database file pages&lt;/strong&gt; until reused.&lt;/p&gt;

&lt;p&gt;To fix this properly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wallras overwrites removed content with zeros, flushes the write-ahead log after deletion, and compacts the database file once existing data is encrypted.&lt;/li&gt;
&lt;li&gt;Every record is also linked in a tamper-evident hash chain—and during deletion, the random salt mixed into that record's fingerprint is wiped ("crypto-shredding") so an attacker cannot brute-force guesses against the ledger hash.&lt;/li&gt;
&lt;li&gt;An automated attack test in CI inspects the raw binary SQLite file and &lt;code&gt;.wal&lt;/code&gt; file after deletion to verify zero plaintext remains.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All 366 automated/attack tests, Semgrep/Bandit/Trivy scans, and live A+ Mozilla Observatory / SSL Labs checks are documented on the &lt;a href="https://wallras.com" rel="noopener noreferrer"&gt;Wallras security page&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Making It Agent-Operated via Zero-Dependency MCP
&lt;/h3&gt;

&lt;p&gt;Developers increasingly debug inside &lt;strong&gt;Claude Code&lt;/strong&gt; or &lt;strong&gt;Cursor&lt;/strong&gt; rather than clicking through separate dashboards.&lt;/p&gt;

&lt;p&gt;Wallras ships a zero-dependency standard-library Python MCP server (&lt;code&gt;wallras-mcp&lt;/code&gt;) and an &lt;a href="https://wallras.com" rel="noopener noreferrer"&gt;&lt;code&gt;llms.txt&lt;/code&gt;&lt;/a&gt; spec:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read-only by default:&lt;/strong&gt; Exposes 22 read-only inspection tools (&lt;code&gt;wallras_drift&lt;/code&gt;, &lt;code&gt;wallras_traces&lt;/code&gt;, &lt;code&gt;wallras_blind_spots&lt;/code&gt;, &lt;code&gt;wallras_prompt_diff&lt;/code&gt;) so your coding agent can diagnose production issues safely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gated prompt promotions:&lt;/strong&gt; Write tools (&lt;code&gt;--enable-writes&lt;/code&gt;) allow Cursor or Claude to promote a prompt update to &lt;code&gt;production&lt;/code&gt; &lt;strong&gt;only if it passes your regression test suite first&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Looking for Honest Engineering Feedback
&lt;/h3&gt;

&lt;p&gt;Payments aren't even turned on yet while I validate proof-of-concept—every plan up to Scale is &lt;strong&gt;100% free to try&lt;/strong&gt; with zero telemetry or prompt data leaving your machine.&lt;/p&gt;

&lt;p&gt;Since I don't have a multi-GPU rig or heavy API budget to stress-test high concurrency, I would love feedback from anyone running local models or production LLM apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quickstart &amp;amp; Docs:&lt;/strong&gt; &lt;a href="https://://wallras.com" rel="noopener noreferrer"&gt;://wallras.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Attack Suite:&lt;/strong&gt; &lt;a href="https://wallras.com" rel="noopener noreferrer"&gt;://wallras.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to roast the math, proxy overhead, or SQLite/Postgres architecture in the comments!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb6u1bbo8kqsy0n8xdxh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb6u1bbo8kqsy0n8xdxh1.png" alt=" " width="703" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>security</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
