<?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: sravan27</title>
    <description>The latest articles on DEV Community by sravan27 (@sravan27).</description>
    <link>https://dev.to/sravan27</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3887565%2Fa1b9fa16-7e94-48fd-b960-fc7c05b0596f.png</url>
      <title>DEV Community: sravan27</title>
      <link>https://dev.to/sravan27</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sravan27"/>
    <language>en</language>
    <item>
      <title>I found silent data-loss bugs in 5 production databases this month - here's the open-source checker</title>
      <dc:creator>sravan27</dc:creator>
      <pubDate>Thu, 04 Jun 2026 14:44:33 +0000</pubDate>
      <link>https://dev.to/sravan27/i-found-silent-data-loss-bugs-in-5-production-databases-this-month-heres-the-open-source-checker-hf1</link>
      <guid>https://dev.to/sravan27/i-found-silent-data-loss-bugs-in-5-production-databases-this-month-heres-the-open-source-checker-hf1</guid>
      <description>&lt;p&gt;Most database bugs throw errors. The dangerous ones don't — they quietly return the &lt;strong&gt;wrong rows&lt;/strong&gt;. No exception, no log line, just a query that silently drops or over‑matches data. That's the worst kind of bug, because nothing tells you it happened.&lt;/p&gt;

&lt;p&gt;This month I went hunting for exactly that failure mode in JavaScript databases — the client‑side, embedded, and sync databases that re‑implement SQL‑ish operators (&lt;code&gt;LIKE&lt;/code&gt;, case‑insensitive match, range comparison) in JS. I found it, and got fixes merged or under review, in &lt;strong&gt;five production databases&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Database&lt;/th&gt;
&lt;th&gt;Bug&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PowerSync&lt;/td&gt;
&lt;td&gt;LIKE / range semantics&lt;/td&gt;
&lt;td&gt;merged (#644)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rocicorp's Zero&lt;/td&gt;
&lt;td&gt;range / comparison&lt;/td&gt;
&lt;td&gt;merged (#6083, #6088)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;InstantDB&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;$like&lt;/code&gt; / &lt;code&gt;$ilike&lt;/code&gt; newline&lt;/td&gt;
&lt;td&gt;merged (#2714)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ElectricSQL&lt;/td&gt;
&lt;td&gt;LIKE newline + escaped wildcards&lt;/td&gt;
&lt;td&gt;PR #4437&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dexie&lt;/td&gt;
&lt;td&gt;case‑fold drops rows&lt;/td&gt;
&lt;td&gt;PR #2306&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Then I packaged the audit into an open‑source tool so you can run it on &lt;strong&gt;your&lt;/strong&gt; database: &lt;a href="https://github.com/sravan27/silentdrop" rel="noopener noreferrer"&gt;silentdrop&lt;/a&gt; — &lt;code&gt;npm i silentdrop&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A concrete one: Dexie silently drops rows
&lt;/h2&gt;

&lt;p&gt;Dexie is the dominant IndexedDB wrapper (~2M downloads/week). Its &lt;code&gt;equalsIgnoreCase&lt;/code&gt; walks the index assuming case conversion is length‑preserving. It isn't — German &lt;code&gt;ß&lt;/code&gt; → &lt;code&gt;SS&lt;/code&gt;, ligatures &lt;code&gt;ﬁ&lt;/code&gt; → &lt;code&gt;FI&lt;/code&gt;, Turkish &lt;code&gt;İ&lt;/code&gt;. So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;straße&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// expected: ['straße', 'STRAßE', 'Straße']&lt;/span&gt;
&lt;span class="c1"&gt;// actual:   ['straße', 'Straße']   ← 'STRAßE' silently dropped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No error. A row that matches by the database's own case‑insensitive contract simply isn't returned. (Reported as Dexie #2306.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it happens
&lt;/h2&gt;

&lt;p&gt;These engines compile &lt;code&gt;LIKE&lt;/code&gt; to a RegExp, or compare strings with JS operators, and the gaps from real SQL semantics are invisible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;LIKE&lt;/code&gt; and newlines&lt;/strong&gt; — in SQL, &lt;code&gt;%&lt;/code&gt; matches any sequence &lt;em&gt;including&lt;/em&gt; &lt;code&gt;\n&lt;/code&gt;. A RegExp without the &lt;code&gt;dotAll&lt;/code&gt; flag silently misses rows containing newlines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;LIKE&lt;/code&gt; metacharacters&lt;/strong&gt; — &lt;code&gt;LIKE 'a.b'&lt;/code&gt; must match the literal &lt;code&gt;a.b&lt;/code&gt;, not &lt;code&gt;axb&lt;/code&gt;. Translate to RegExp without escaping and you over‑match — a correctness &lt;em&gt;and&lt;/em&gt; injection risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Case folds that change length&lt;/strong&gt; — the Dexie one above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non‑BMP ordering&lt;/strong&gt; — SQL/Postgres orders text by code point; naive JS comparison orders by UTF‑16 code unit, so an emoji (U+1F600) sorts &lt;em&gt;below&lt;/em&gt; U+F000 and a range query silently drops it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The checker
&lt;/h2&gt;

&lt;p&gt;silentdrop runs these cases against your database's operators and reports the divergences. You wire a tiny adapter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;check&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;silentdrop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;         &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* clear the store */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* insert string values */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* run a LIKE query, return matches */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;ilike&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* case-insensitive equality */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* values &amp;gt; bound */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it against Dexie and it flags the case‑fold drop live; run it against AlaSQL and it passes the LIKE tests but flags the code‑point ordering divergence. A complete, runnable Dexie example is in the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you should care
&lt;/h2&gt;

&lt;p&gt;If you store names, addresses, search terms — anything with international characters — and you rely on case‑insensitive lookup or range queries for correctness (uniqueness checks, "is this taken?", access checks, "everything ≥ X"), you may be &lt;strong&gt;silently losing rows in production today&lt;/strong&gt;. The fix is usually small. &lt;em&gt;Finding&lt;/em&gt; it is the hard part — that's what the tool is for.&lt;/p&gt;

&lt;p&gt;MIT‑licensed, zero runtime dependencies: &lt;strong&gt;&lt;a href="https://github.com/sravan27/silentdrop" rel="noopener noreferrer"&gt;https://github.com/sravan27/silentdrop&lt;/a&gt;&lt;/strong&gt;. PRs adding adapters for more databases are very welcome.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If your sync/database layer is correctness‑critical and you'd rather have the whole operator surface hardened by hand — the same pass behind the five databases above — I take that on as a fixed 48‑hour sprint; details are in the repo README.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>database</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Your structured outputs are probably less portable than you think</title>
      <dc:creator>sravan27</dc:creator>
      <pubDate>Sun, 19 Apr 2026 16:22:26 +0000</pubDate>
      <link>https://dev.to/sravan27/your-structured-outputs-are-probably-less-portable-than-you-think-2p1l</link>
      <guid>https://dev.to/sravan27/your-structured-outputs-are-probably-less-portable-than-you-think-2p1l</guid>
      <description>&lt;p&gt;Structured outputs are less portable across LLM providers than they look.&lt;/p&gt;

&lt;p&gt;A schema change can seem harmless and still break one provider while passing another.&lt;/p&gt;

&lt;p&gt;I built Schema Gateway for that exact failure mode.&lt;/p&gt;

&lt;p&gt;What it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;compile one schema into provider-ready request shapes&lt;/li&gt;
&lt;li&gt;diff a baseline schema against a candidate schema&lt;/li&gt;
&lt;li&gt;lint for portability issues&lt;/li&gt;
&lt;li&gt;normalize payloads against a schema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s built for people working across providers like OpenAI, Gemini, Anthropic, and Ollama, where “structured output support” sounds similar until the edge cases show up.&lt;/p&gt;

&lt;p&gt;There’s an open-source/local path, plus a hosted Starter Access if you want to try the hosted API quickly.&lt;/p&gt;

&lt;p&gt;Main thing I’m looking for:&lt;br&gt;
feedback from people actually shipping structured outputs or comparing providers in production. I’m especially interested in whether this pain is strong enough to justify a dedicated guardrail in real workflows.&lt;/p&gt;

&lt;p&gt;Live here:&lt;br&gt;
&lt;a href="https://schema-gateway.sridharsravan.workers.dev/" rel="noopener noreferrer"&gt;https://schema-gateway.sridharsravan.workers.dev/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
