<?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>Forem: Matias Affolter</title>
    <description>The latest articles on Forem by Matias Affolter (@matias_affolter).</description>
    <link>https://forem.com/matias_affolter</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%2F1810003%2Faded81b1-0a4b-4705-9cc7-6d29db0d4b0f.png</url>
      <title>Forem: Matias Affolter</title>
      <link>https://forem.com/matias_affolter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/matias_affolter"/>
    <language>en</language>
    <item>
      <title>I Benchmarked LacertaDB &amp; PouchDB — Here's What Happened</title>
      <dc:creator>Matias Affolter</dc:creator>
      <pubDate>Thu, 26 Mar 2026 17:29:39 +0000</pubDate>
      <link>https://forem.com/matias_affolter/i-benchmarked-lacertadb-pouchdb-heres-what-happened-3l9n</link>
      <guid>https://forem.com/matias_affolter/i-benchmarked-lacertadb-pouchdb-heres-what-happened-3l9n</guid>
      <description>&lt;p&gt;LacertaDB vs PouchDB: a head-to-head performance comparison of two browser-native document databases, and why your serializer matters more than you think.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Browser Database Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Every browser database eventually hits the same wall: &lt;strong&gt;serialization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your data has to be transformed before it hits IndexedDB, and transformed back when it comes out. Most libraries use JSON. Some use CBOR or MessagePack. The choice of serializer silently determines your throughput ceiling — and most developers never question it.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://www.npmjs.com/package/@pixagram/lacerta-db" rel="noopener noreferrer"&gt;LacertaDB&lt;/a&gt; to be the fastest browser-native document database possible. Along the way, I had to build its serializer from scratch too, because nothing on npm was fast enough &lt;em&gt;or&lt;/em&gt; complete enough. Then I ran it against PouchDB — the established king of browser databases — to see where things actually stand.&lt;/p&gt;

&lt;p&gt;Here are the numbers. No cherry-picking, no synthetic micro-ops. Real document CRUD at scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Benchmark Setup
&lt;/h2&gt;

&lt;p&gt;Both databases ran identical workloads in the same browser tab, same machine, same IndexedDB backend. The test: &lt;strong&gt;5,000 documents&lt;/strong&gt; with ~200-byte payloads, covering the five operations that matter in a real app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bulk Write&lt;/strong&gt; — insert all documents in a single batch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read All&lt;/strong&gt; — retrieve every document&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query (filter)&lt;/strong&gt; — find documents matching a field condition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulk Update&lt;/strong&gt; — modify every document&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete All&lt;/strong&gt; — remove everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LacertaDB uses &lt;code&gt;batchAdd&lt;/code&gt; / &lt;code&gt;getAll&lt;/code&gt; / &lt;code&gt;query&lt;/code&gt; / &lt;code&gt;batchUpdate&lt;/code&gt; / &lt;code&gt;clear&lt;/code&gt;.&lt;br&gt;
PouchDB uses &lt;code&gt;bulkDocs&lt;/code&gt; / &lt;code&gt;allDocs&lt;/code&gt; / &lt;code&gt;find&lt;/code&gt; (with pouchdb-find) / &lt;code&gt;bulkDocs&lt;/code&gt; / &lt;code&gt;bulkDocs&lt;/code&gt; with &lt;code&gt;_deleted&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both are fair comparisons of each library's recommended bulk API.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;LacertaDB&lt;/th&gt;
&lt;th&gt;PouchDB 7.3&lt;/th&gt;
&lt;th&gt;Speedup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bulk Write&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;532 ms&lt;/td&gt;
&lt;td&gt;2,664 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Read All&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;146 ms&lt;/td&gt;
&lt;td&gt;356 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.4×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;124 ms&lt;/td&gt;
&lt;td&gt;399 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.2×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bulk Update&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;101 ms&lt;/td&gt;
&lt;td&gt;2,708 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;26.8×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Delete All&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;239 ms&lt;/td&gt;
&lt;td&gt;2,573 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10.8×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The gap ranges from &lt;strong&gt;2.4× to nearly 27×&lt;/strong&gt;, depending on the operation. Writes and deletes show the biggest difference — and those are precisely the operations where serialization overhead dominates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Throughput in Context
&lt;/h3&gt;

&lt;p&gt;At 5,000 documents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LacertaDB sustained &lt;strong&gt;~9,400 writes/sec&lt;/strong&gt; and &lt;strong&gt;~34,000 reads/sec&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;PouchDB managed &lt;strong&gt;~1,900 writes/sec&lt;/strong&gt; and &lt;strong&gt;~14,600 reads/sec&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't a marginal difference. For offline-first apps syncing hundreds of records, or Web3 dApps caching blockchain state locally, the gap between "feels instant" and "shows a spinner" lives right in this range.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the Gap? It's the Serializer.
&lt;/h2&gt;

&lt;p&gt;PouchDB stores documents as JSON. That's fine for simple objects, but JSON has well-known limitations: no &lt;code&gt;Date&lt;/code&gt;, no &lt;code&gt;undefined&lt;/code&gt;, no &lt;code&gt;Map&lt;/code&gt;, no &lt;code&gt;Set&lt;/code&gt;, no &lt;code&gt;RegExp&lt;/code&gt;, no typed arrays, no binary data. And JSON.stringify/parse, while native C++ under the hood, still has to traverse every property, escape every string, and produce a text representation that's larger than the source data.&lt;/p&gt;

&lt;p&gt;LacertaDB uses &lt;a href="https://www.npmjs.com/package/@pixagram/turboserial" rel="noopener noreferrer"&gt;TurboSerial&lt;/a&gt;, a binary serializer I built specifically for this problem. The design goals were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Serialize everything JavaScript can hold&lt;/strong&gt; — not just JSON-safe types&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Produce smaller output&lt;/strong&gt; — binary, no delimiters, no escaping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be faster than the alternatives&lt;/strong&gt; — including CBOR and MessagePack&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  TurboSerial vs MessagePack vs CBOR
&lt;/h3&gt;

&lt;p&gt;I ran TurboSerial against the two established binary serialization formats. The benchmark measures both throughput (ops/sec) and output size across three payload profiles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test Case&lt;/th&gt;
&lt;th&gt;MessagePack&lt;/th&gt;
&lt;th&gt;CBOR&lt;/th&gt;
&lt;th&gt;TurboSerial&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Small Data&lt;/strong&gt; (API response)&lt;/td&gt;
&lt;td&gt;20,101 ops/s · 34B&lt;/td&gt;
&lt;td&gt;112,360 ops/s · 36B&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;176,991 ops/s&lt;/strong&gt; · 62B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Medium Data&lt;/strong&gt; (array of objects)&lt;/td&gt;
&lt;td&gt;334 ops/s · 4,093B&lt;/td&gt;
&lt;td&gt;3,460 ops/s · 4,168B&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;5,587 ops/s&lt;/strong&gt; · 4,809B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Large Data&lt;/strong&gt; (TypedArray 0.2MB)&lt;/td&gt;
&lt;td&gt;711 ops/s · 200,005B&lt;/td&gt;
&lt;td&gt;341 ops/s · 200,005B&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;2,703 ops/s&lt;/strong&gt; · 200,023B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;TurboSerial is consistently &lt;strong&gt;1.5–8× faster&lt;/strong&gt; than both MessagePack and CBOR across payload sizes. The output is slightly larger on small payloads (it encodes richer type metadata), but the throughput advantage more than compensates — especially at the medium and large data sizes that matter in a database context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type Coverage: Where JSON, CBOR, and TurboSerial Diverge
&lt;/h3&gt;

&lt;p&gt;This is the part that rarely makes it into benchmark posts, but it's what actually matters when you're building a real app. Here's what each format can serialize natively:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;JSON&lt;/th&gt;
&lt;th&gt;MessagePack&lt;/th&gt;
&lt;th&gt;CBOR&lt;/th&gt;
&lt;th&gt;TurboSerial&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Strings, Numbers, Booleans, null&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nested Objects / Arrays&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Date&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (tag)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Map&lt;/code&gt; / &lt;code&gt;Set&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RegExp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BigInt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (tag)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ArrayBuffer&lt;/code&gt; / TypedArrays&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Int8Array&lt;/code&gt; through &lt;code&gt;Float64Array&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Error&lt;/code&gt; objects&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;URL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sparse Arrays&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Infinity&lt;/code&gt;, &lt;code&gt;-Infinity&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;-0&lt;/code&gt; (negative zero)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;JSON covers about 7 types. CBOR and MessagePack stretch to ~12 with tags and binary extensions. TurboSerial natively handles &lt;strong&gt;20+ JavaScript types&lt;/strong&gt; — including the edge cases that silently break your data when you use JSON (like &lt;code&gt;undefined&lt;/code&gt; being stripped from objects, or &lt;code&gt;Date&lt;/code&gt; becoming a string you have to manually parse back).&lt;/p&gt;

&lt;p&gt;When your database serializer supports &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, &lt;code&gt;RegExp&lt;/code&gt;, and typed arrays out of the box, you stop writing workaround code. Your documents go in, and they come out &lt;em&gt;identical&lt;/em&gt;. No reviver functions, no manual reconstruction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Beyond Raw Speed: What LacertaDB Actually Offers
&lt;/h2&gt;

&lt;p&gt;Performance is one axis. Here's what the full picture looks like against PouchDB:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;LacertaDB&lt;/th&gt;
&lt;th&gt;PouchDB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bundle size (minified)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~110 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~200 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serialization&lt;/td&gt;
&lt;td&gt;TurboSerial (binary)&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage backend&lt;/td&gt;
&lt;td&gt;IndexedDB + OPFS + localStorage&lt;/td&gt;
&lt;td&gt;IndexedDB (+ adapters)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query syntax&lt;/td&gt;
&lt;td&gt;MongoDB-style, 20+ operators&lt;/td&gt;
&lt;td&gt;Mango (pouchdb-find plugin)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index types&lt;/td&gt;
&lt;td&gt;B-Tree, Hash, Full-text, Geo&lt;/td&gt;
&lt;td&gt;B-Tree equivalent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encryption&lt;/td&gt;
&lt;td&gt;AES-GCM-256, PBKDF2 Master Key Wrap&lt;/td&gt;
&lt;td&gt;❌ (requires plugin)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aggregation pipeline&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;$match&lt;/code&gt;, &lt;code&gt;$group&lt;/code&gt;, &lt;code&gt;$sort&lt;/code&gt;, &lt;code&gt;$lookup&lt;/code&gt;…&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geospatial queries&lt;/td&gt;
&lt;td&gt;QuadTree &lt;code&gt;$near&lt;/code&gt;, &lt;code&gt;$within&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full-text search&lt;/td&gt;
&lt;td&gt;Built-in with CJK support&lt;/td&gt;
&lt;td&gt;❌ (requires plugin)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caching strategies&lt;/td&gt;
&lt;td&gt;LRU / LFU / TTL per collection&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary attachments&lt;/td&gt;
&lt;td&gt;OPFS-backed&lt;/td&gt;
&lt;td&gt;Blob-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CouchDB sync&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js / server-side&lt;/td&gt;
&lt;td&gt;❌ (browser-only)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The honest tradeoff: PouchDB has CouchDB sync and server-side support. If you need those, PouchDB is the right tool. LacertaDB is browser-native by design — it trades server compatibility for raw performance, smaller bundles, and features you'd otherwise need three plugins to bolt onto PouchDB.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Reach for LacertaDB
&lt;/h2&gt;

&lt;p&gt;LacertaDB was built for a specific class of application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offline-first PWAs&lt;/strong&gt; that need to cache and query significant amounts of data locally without UI jank&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web3 dApps&lt;/strong&gt; that store blockchain state, wallet keys (with real encryption), or NFT metadata client-side&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data-heavy SPAs&lt;/strong&gt; where the difference between 100ms and 2,700ms on a bulk write is the difference between feeling native and feeling broken&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apps storing rich JavaScript types&lt;/strong&gt; — if your data model uses &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, &lt;code&gt;Date&lt;/code&gt;, typed arrays, or &lt;code&gt;BigInt&lt;/code&gt;, you'll stop fighting your serializer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need CouchDB replication or server-side rendering, PouchDB remains excellent. But if your database lives in the browser and performance is non-negotiable, LacertaDB is worth a look.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @pixagram/lacerta-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;LacertaDB&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="s1"&gt;@pixagram/lacerta-db&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;lacerta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LacertaDB&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myapp&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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&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="nf"&gt;createCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Store a document with types JSON can't handle&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;joined&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lang&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]),&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beta-tester&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;71&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// PNG header bytes&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Query it back — every type is preserved, no revivers needed&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$contains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source is on &lt;a href="https://github.com/pixagram-blockchain/LacertaDB" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, the package is on &lt;a href="https://www.npmjs.com/package/@pixagram/lacerta-db" rel="noopener noreferrer"&gt;npm&lt;/a&gt;, and the benchmark playground is included in the repo.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;LacertaDB is MIT-licensed and built by &lt;a href="https://pixagram.io" rel="noopener noreferrer"&gt;Pixagram SA&lt;/a&gt; in Zug, Switzerland.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>database</category>
    </item>
    <item>
      <title>A deep dive into LacertaDB</title>
      <dc:creator>Matias Affolter</dc:creator>
      <pubDate>Wed, 17 Dec 2025 13:18:17 +0000</pubDate>
      <link>https://forem.com/matias_affolter/a-deep-dive-into-lacertadb-1apc</link>
      <guid>https://forem.com/matias_affolter/a-deep-dive-into-lacertadb-1apc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;LacertaDB: Why We Built a MongoDB-Like Database That Runs Entirely in Your Browser &lt;a href="https://codepen.io/Matias-Affolter/pen/ogjrQdB" rel="noopener noreferrer"&gt;DEMO&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;How we created a full-featured document database with encryption, indexing, and aggregation pipelines — all running client-side with zero backend.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Nobody Was Solving
&lt;/h2&gt;

&lt;p&gt;Picture this: You're building a Web3 wallet, an offline-first PWA, or a privacy-focused note-taking app. You need to store sensitive data locally. Your options?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5MB limit, no queries, plaintext only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raw IndexedDB&lt;/td&gt;
&lt;td&gt;Verbose API, no encryption, manual indexing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQLite WASM&lt;/td&gt;
&lt;td&gt;2MB+ bundle, SQL syntax, no native encryption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PouchDB&lt;/td&gt;
&lt;td&gt;Sync-focused, no built-in encryption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dexie.js&lt;/td&gt;
&lt;td&gt;Great queries, but no encryption or OPFS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We needed something that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Stores encrypted documents with zero backend&lt;/li&gt;
&lt;li&gt;✅ Supports MongoDB-style queries&lt;/li&gt;
&lt;li&gt;✅ Handles binary files (images, PDFs)&lt;/li&gt;
&lt;li&gt;✅ Has proper indexes for performance&lt;/li&gt;
&lt;li&gt;✅ Works entirely offline&lt;/li&gt;
&lt;li&gt;✅ Fits in a reasonable bundle size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing existed. So we built &lt;strong&gt;LacertaDB&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes LacertaDB Different
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 🔐 Military-Grade Encryption, Zero Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// That's it. Your entire database is now encrypted.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSecureDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vault&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123456&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Every document is automatically encrypted with AES-GCM-256&lt;/span&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="nf"&gt;createCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secrets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sk-live-xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;privateNotes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is encrypted at rest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AES-GCM-256&lt;/strong&gt; encryption (same as banks use)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PBKDF2&lt;/strong&gt; key derivation with 100,000 iterations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HMAC&lt;/strong&gt; integrity verification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constant-time comparisons&lt;/strong&gt; (no timing attacks)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most browser databases bolt encryption on as an afterthought. In LacertaDB, it's a first-class citizen — and it actually works when you change your PIN:&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="c1"&gt;// This re-encrypts EVERY document in the database&lt;/span&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="nf"&gt;changePin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;oldPin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;newStrongerPin!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've seen "encrypted" databases that lose all your data when you change the password. We fixed that.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. 🔍 Real MongoDB-Style Queries
&lt;/h3&gt;

&lt;p&gt;Not "inspired by MongoDB." Actually compatible:&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="c1"&gt;// Find active premium users over 18, sorted by signup date&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;$and&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enterprise&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$regex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@company&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.com$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;projection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;20+ operators supported:&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;Category&lt;/th&gt;
&lt;th&gt;Operators&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Comparison&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;$eq&lt;/code&gt;, &lt;code&gt;$ne&lt;/code&gt;, &lt;code&gt;$gt&lt;/code&gt;, &lt;code&gt;$gte&lt;/code&gt;, &lt;code&gt;$lt&lt;/code&gt;, &lt;code&gt;$lte&lt;/code&gt;, &lt;code&gt;$in&lt;/code&gt;, &lt;code&gt;$nin&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logical&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;$and&lt;/code&gt;, &lt;code&gt;$or&lt;/code&gt;, &lt;code&gt;$not&lt;/code&gt;, &lt;code&gt;$nor&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Element&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;$exists&lt;/code&gt;, &lt;code&gt;$type&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Array&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;$all&lt;/code&gt;, &lt;code&gt;$elemMatch&lt;/code&gt;, &lt;code&gt;$size&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;$regex&lt;/code&gt;, &lt;code&gt;$text&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plus a full &lt;strong&gt;aggregation pipeline&lt;/strong&gt;:&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="c1"&gt;// Sales report grouped by category&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;startOfMonth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$category&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;revenue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$sum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$amount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;avgOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$avg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$amount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;revenue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs &lt;strong&gt;entirely in the browser&lt;/strong&gt;. No server. No network request.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. ⚡ Four Index Types for Real Performance
&lt;/h3&gt;

&lt;p&gt;Queries on 10,000 documents without indexes? Slow.&lt;br&gt;
With indexes? Instant.&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="c1"&gt;// B-Tree for range queries and sorting&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Hash for lightning-fast exact matches&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Full-text search&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Geospatial for location queries&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;location&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;geo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The geo index supports real geospatial queries:&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="c1"&gt;// Find coffee shops within 2km&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nearby&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;places&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$near&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;47.3769&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;8.5417&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;maxDistance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;// kilometers&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coffee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. 📁 Native Binary File Storage with OPFS
&lt;/h3&gt;

&lt;p&gt;Most browser databases choke on files. LacertaDB uses the &lt;strong&gt;Origin Private File System&lt;/strong&gt; (OPFS) — a modern API that gives you a real filesystem:&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="c1"&gt;// Store a document with file attachments&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;docId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Project Proposal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;proposalPDF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// File object&lt;/span&gt;
      &lt;span class="nx"&gt;coverImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// Blob&lt;/span&gt;
      &lt;span class="nx"&gt;spreadsheet&lt;/span&gt;      &lt;span class="c1"&gt;// Another File&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve with attachments&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;includeAttachments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// doc._attachments = [{ name: 'proposal.pdf', data: Uint8Array, ... }]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Files are stored separately from document data, so your IndexedDB doesn't bloat. And yes, they're encrypted too.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. 🏗️ Fractal Architecture
&lt;/h3&gt;

&lt;p&gt;LacertaDB follows a "fractal" design where each layer encapsulates complexity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LacertaDB
└── Database (encryption, settings, migrations)
    └── Collection (CRUD, queries, indexes, events)
        └── Document (serialization, compression, packing)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means you can use just what you need:&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="c1"&gt;// Full database with collections&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&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="nf"&gt;createCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Or just fast key-value storage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prefs&lt;/span&gt; &lt;span class="o"&gt;=&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;quickStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#00ff88&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Use Case: Web3 Wallet
&lt;/h2&gt;

&lt;p&gt;Here's how we use LacertaDB for secure key storage in a crypto wallet:&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;LacertaDB&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="s1"&gt;@pixagram/lacertadb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WalletManager&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;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userPin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lacerta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LacertaDB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSecureDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wallet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userPin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wallets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wallets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Index for fast lookups&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wallets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&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;createWallet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateKeyPair&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Store encrypted private key in secure vault&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;storePrivateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-pk`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Store public metadata&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wallets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// permanent = protected from cleanup&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&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;signTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;walletName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Retrieve decrypted private key&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrivateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;walletName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-pk`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;signWithKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&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;exportBackup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;backupPassword&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Export everything, encrypted with a separate password&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createBackup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;backupPassword&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The private keys are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Encrypted with AES-GCM-256&lt;/li&gt;
&lt;li&gt;Key derived from user PIN via PBKDF2&lt;/li&gt;
&lt;li&gt;Never exposed in plaintext&lt;/li&gt;
&lt;li&gt;Separate from document storage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is &lt;strong&gt;production code&lt;/strong&gt; we ship.&lt;/p&gt;




&lt;h2&gt;
  
  
  Performance That Scales
&lt;/h2&gt;

&lt;p&gt;We benchmarked LacertaDB against common operations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;1,000 docs&lt;/th&gt;
&lt;th&gt;10,000 docs&lt;/th&gt;
&lt;th&gt;100,000 docs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Insert (batch)&lt;/td&gt;
&lt;td&gt;45ms&lt;/td&gt;
&lt;td&gt;380ms&lt;/td&gt;
&lt;td&gt;3.2s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query (indexed)&lt;/td&gt;
&lt;td&gt;2ms&lt;/td&gt;
&lt;td&gt;3ms&lt;/td&gt;
&lt;td&gt;8ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query (full scan)&lt;/td&gt;
&lt;td&gt;12ms&lt;/td&gt;
&lt;td&gt;95ms&lt;/td&gt;
&lt;td&gt;890ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aggregation&lt;/td&gt;
&lt;td&gt;8ms&lt;/td&gt;
&lt;td&gt;65ms&lt;/td&gt;
&lt;td&gt;580ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With proper indexes, queries stay fast even at scale. The built-in &lt;strong&gt;performance monitor&lt;/strong&gt; helps you optimize:&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="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;performanceMonitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startMonitoring&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// ... do operations ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;performanceMonitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStats&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// {&lt;/span&gt;
&lt;span class="c1"&gt;//   opsPerSec: 245,&lt;/span&gt;
&lt;span class="c1"&gt;//   avgLatency: '4.12',&lt;/span&gt;
&lt;span class="c1"&gt;//   cacheHitRate: '89.3',&lt;/span&gt;
&lt;span class="c1"&gt;//   memoryUsageMB: '12.45'&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;performanceMonitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOptimizationTips&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// ['Consider adding an index on frequently queried fields']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Caching Layer Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Every query doesn't need to hit IndexedDB. LacertaDB includes three caching strategies:&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="c1"&gt;// LRU (Least Recently Used) - default&lt;/span&gt;
&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configureCacheStrategy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lru&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// LFU (Least Frequently Used) - for hot data&lt;/span&gt;
&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configureCacheStrategy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lfu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// TTL (Time To Live) - for expiring data&lt;/span&gt;
&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configureCacheStrategy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ttl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt; &lt;span class="c1"&gt;// 1 minute&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cache hit rates of 80%+ are common, meaning 4 out of 5 queries return instantly from memory.&lt;/p&gt;




&lt;h2&gt;
  
  
  Schema Migrations Done Right
&lt;/h2&gt;

&lt;p&gt;Your data schema will evolve. LacertaDB has you covered:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;migration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MigrationManager&lt;/span&gt;&lt;span class="p"&gt;(&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;migration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addMigration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Add user roles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;write&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Migrate forward&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;migration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runMigrations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Oops, rollback&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;migration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Migrations run per-document across all collections, with full rollback support.&lt;/p&gt;




&lt;h2&gt;
  
  
  Event-Driven When You Need It
&lt;/h2&gt;

&lt;p&gt;Hook into document lifecycle events:&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="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterAdd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;syncToCloud&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document_created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beforeDelete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docId&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;createBackup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Available events:&lt;/span&gt;
&lt;span class="c1"&gt;// beforeAdd, afterAdd&lt;/span&gt;
&lt;span class="c1"&gt;// beforeUpdate, afterUpdate  &lt;/span&gt;
&lt;span class="c1"&gt;// beforeDelete, afterDelete&lt;/span&gt;
&lt;span class="c1"&gt;// beforeGet, afterGet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why "Lacerta"?
&lt;/h2&gt;

&lt;p&gt;Lacerta is the Latin word for lizard — specifically the genus that includes the common wall lizard. Why a lizard?&lt;/p&gt;

&lt;p&gt;🦎 &lt;strong&gt;Adaptable&lt;/strong&gt;: Lives anywhere, eats anything&lt;br&gt;
🦎 &lt;strong&gt;Fast&lt;/strong&gt;: Moves in bursts of incredible speed&lt;br&gt;
🦎 &lt;strong&gt;Resilient&lt;/strong&gt;: Survives harsh conditions&lt;br&gt;
🦎 &lt;strong&gt;Efficient&lt;/strong&gt;: Cold-blooded = minimal energy waste&lt;/p&gt;

&lt;p&gt;That's what we wanted for browser storage: adaptable to any use case, fast when it matters, resilient to failure, efficient with resources.&lt;/p&gt;

&lt;p&gt;Plus, we're based in Zug, Switzerland 🇨🇭 — lizards love sunny Alpine rocks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @pixagram/lacertadb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;LacertaDB&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="s1"&gt;@pixagram/lacertadb&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;lacerta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LacertaDB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Unencrypted database&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myapp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Or encrypted&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secureDb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lacerta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSecureDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vault&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myPin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create collection and go&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&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="nf"&gt;createCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Try LacertaDB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;pending&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;We're actively developing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔄 &lt;strong&gt;Sync adapters&lt;/strong&gt; for optional cloud backup&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Query planner&lt;/strong&gt; for automatic index selection&lt;/li&gt;
&lt;li&gt;🧪 &lt;strong&gt;Schema validation&lt;/strong&gt; with JSON Schema&lt;/li&gt;
&lt;li&gt;🔌 &lt;strong&gt;Plugin system&lt;/strong&gt; for custom index types&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;npm&lt;/strong&gt;: &lt;code&gt;@pixagram/lacertadb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Docs&lt;/strong&gt;: &lt;a href="https://github.com/pixagram/lacertadb" rel="noopener noreferrer"&gt;github.com/pixagram/lacertadb&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐛 &lt;strong&gt;Issues&lt;/strong&gt;: We actually respond!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building anything that needs local-first, encrypted, queryable storage in the browser — give LacertaDB a try. We think you'll love it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with 🦎 by &lt;a href="https://pixagram.io" rel="noopener noreferrer"&gt;Pixagram&lt;/a&gt; in Zug, Switzerland&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What browser storage challenges have you faced? Drop a comment below!&lt;/strong&gt; 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>security</category>
      <category>database</category>
    </item>
    <item>
      <title>How We Built an AI That Transforms Your Photos Into Pixel Art in 10 Seconds (And Why It Matters for Web3)</title>
      <dc:creator>Matias Affolter</dc:creator>
      <pubDate>Tue, 28 Oct 2025 10:31:55 +0000</pubDate>
      <link>https://forem.com/matias_affolter/how-we-built-an-ai-that-transforms-your-photos-into-pixel-art-in-10-seconds-and-why-it-matters-for-47pk</link>
      <guid>https://forem.com/matias_affolter/how-we-built-an-ai-that-transforms-your-photos-into-pixel-art-in-10-seconds-and-why-it-matters-for-47pk</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; We created an AI-powered pixel art generator that preserves facial features while creating authentic retro art. But here's the kicker – pixel art is 100x lighter than regular images, making it perfect for storing forever on the blockchain. Let me show you how we did it. &lt;a href="https://huggingface.co/spaces/primerz/pixagram" rel="noopener noreferrer"&gt;TRY IT&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem We're Solving
&lt;/h2&gt;

&lt;p&gt;Picture this: You love NFTs, but uploading a 2MB photo to the blockchain costs you an arm and a leg. Most NFT platforms don't actually store your art on-chain – they just store a link that could break tomorrow. Meanwhile, creating genuine pixel art by hand takes hours, even for professionals.&lt;/p&gt;

&lt;p&gt;We thought: &lt;em&gt;What if we could convert any photo into authentic pixel art that's light enough to live permanently on-chain?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's how &lt;a href="https://pixagram.io" rel="noopener noreferrer"&gt;Pixagram&lt;/a&gt; was born.&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.amazonaws.com%2Fuploads%2Farticles%2F7qj5lfvvhfx5kk9483e5.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2F7qj5lfvvhfx5kk9483e5.jpg" alt="Screenshot Pixel Art Conversion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Magic Behind the Curtain
&lt;/h2&gt;

&lt;p&gt;Our AI pipeline is like a sophisticated assembly line, where each station does one specific job really well. Here's what happens when you upload a photo:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://pixagram.io/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fpixa-pics%2Fpixa-pics.github.io%2Fmaster%2Fsrc%2Fimages%2Fog%2Fpixagram_logo_og_s.jpeg" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://pixagram.io/" rel="noopener noreferrer" class="c-link"&gt;
            Pixagram.io - Social Media Blockchain
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Use the social media blockchain — Pixagram — where your artworks become as enduring as diamond. Transform photos into pixel art using pixa.pics, then mint, post, and thrive on our NFT-powered network.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpixagram.io%2Fsrc%2Fimages%2Ffavicon.ico"&gt;
          pixagram.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;h3&gt;
  
  
  1. &lt;strong&gt;Face Detection &amp;amp; Enhancement&lt;/strong&gt; (The Foundation)
&lt;/h3&gt;

&lt;p&gt;First, we use InsightFace to detect faces in your image. But we don't just find the face – we actually &lt;em&gt;understand&lt;/em&gt; it. The system extracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;512-dimensional facial embeddings (basically a mathematical fingerprint of your face)&lt;/li&gt;
&lt;li&gt;Facial keypoints (eyes, nose, mouth positions)&lt;/li&gt;
&lt;li&gt;Age and gender estimates&lt;/li&gt;
&lt;li&gt;Facial structure data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's where it gets interesting: we crop the face with 30% padding around it (for context), then enhance it through multiple stages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resize to optimal dimensions&lt;/li&gt;
&lt;li&gt;Sharpen features (1.5x boost)&lt;/li&gt;
&lt;li&gt;Enhance contrast (1.1x)&lt;/li&gt;
&lt;li&gt;Adjust brightness (1.05x)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of this as giving the AI the best possible view of your face before the transformation begins.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Dual Embedding System&lt;/strong&gt; (The Secret Sauce)
&lt;/h3&gt;

&lt;p&gt;Most AI art generators use one type of embedding. We use &lt;strong&gt;two&lt;/strong&gt; working together:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLIP Embeddings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These understand the &lt;em&gt;semantic meaning&lt;/em&gt; of your face&lt;/li&gt;
&lt;li&gt;They know "this is a smiling woman with blue eyes"&lt;/li&gt;
&lt;li&gt;Perfect for maintaining identity at a conceptual level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;InsightFace Embeddings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These understand the &lt;em&gt;geometric structure&lt;/em&gt; of your face&lt;/li&gt;
&lt;li&gt;They know exact distances between features&lt;/li&gt;
&lt;li&gt;Perfect for preserving facial accuracy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining both, we get the best of semantic understanding AND structural precision.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;The Transformation Pipeline&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now the real magic happens. We use a modified Stable Diffusion XL pipeline with several specialized components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a) Custom Pixel Art LORA&lt;/strong&gt;&lt;br&gt;
We trained a specialized LORA (Low-Rank Adaptation) on authentic pixel art. This teaches the model what genuine pixel art should look like – not just blocky images, but art with proper dithering, limited color palettes, and that nostalgic retro feel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b) InstantID ControlNet&lt;/strong&gt;&lt;br&gt;
This maintains facial structure using the keypoints we extracted earlier. It's like drawing a skeleton that the AI must follow – ensuring your eyes stay where your eyes should be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c) Zoe Depth ControlNet&lt;/strong&gt;&lt;br&gt;
This preserves the 3D structure of your image. It understands depth – what's in front, what's behind – keeping your photo's spatial relationships intact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;d) IP-Adapter Integration&lt;/strong&gt;&lt;br&gt;
This injects our dual embeddings directly into the diffusion process through cross-attention. It's constantly whispering to the AI: "remember, this is what the person's face looks like."&lt;/p&gt;
&lt;h3&gt;
  
  
  4. &lt;strong&gt;Post-Processing Polish&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After generation, we apply color matching in LAB color space. This ensures skin tones stay consistent with the original photo – no random orange or purple faces.&lt;/p&gt;

&lt;p&gt;For faces, we create soft masks with feathered edges, allowing seamless blending between the pixelated transformation and facial features.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Technical Stack
&lt;/h2&gt;

&lt;p&gt;Here's what powers the system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Base Model: Stable Diffusion XL (custom checkpoint: "horizon")
- Face Analysis: InsightFace (AnteLope v2)
- Scheduler: LCM (enables 12-step generation)
- ControlNets: InstantID + Zoe Depth
- Image Encoding: CLIP Vision Model
- Pipeline: Img2Img (preserves structure)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Parameters:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steps: 12 (thanks to LCM scheduler)&lt;/li&gt;
&lt;li&gt;CFG Scale: 1.0-1.5 (LCM sweet spot)&lt;/li&gt;
&lt;li&gt;Img2Img Strength: 0.55 (balances transformation vs. fidelity)&lt;/li&gt;
&lt;li&gt;Identity Preservation: 1.3x (boosted for maximum face accuracy)&lt;/li&gt;
&lt;li&gt;Resolution: Auto-optimized to 896×1152 or 832×1216&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters: The Blockchain Advantage
&lt;/h2&gt;

&lt;p&gt;Here's where things get really interesting. Let's talk numbers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A typical photo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average size: 2-3 MB&lt;/li&gt;
&lt;li&gt;On IPFS: Still requires external hosting&lt;/li&gt;
&lt;li&gt;Link can break if hosting fails&lt;/li&gt;
&lt;li&gt;Expensive to store on-chain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pixagram pixel art:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average size: 15-20 KB&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;That's 100-150x smaller&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Can be embedded directly on-chain&lt;/li&gt;
&lt;li&gt;Stored forever in the blockchain itself&lt;/li&gt;
&lt;li&gt;No external dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Our Blockchain: Built for This
&lt;/h3&gt;

&lt;p&gt;Pixagram runs on a fork of HIVE/STEEM, optimized for social media and NFTs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;72 KB maximum post capacity&lt;/strong&gt; – perfect for pixel art&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3-second block time&lt;/strong&gt; – near-instant confirmation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proof-of-Brain consensus&lt;/strong&gt; – rewards creators&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;24 elected witnesses&lt;/strong&gt; – truly decentralized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you create pixel art on Pixagram, it's not just stored on-chain – it becomes &lt;em&gt;part&lt;/em&gt; of the chain. Your art will exist as long as the blockchain exists. No broken links. No lost hosting. Forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Actually Performs
&lt;/h2&gt;

&lt;p&gt;Let's be real about what this AI can and can't do:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it excels at:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portraits with clear facial features&lt;/li&gt;
&lt;li&gt;Photos with good lighting&lt;/li&gt;
&lt;li&gt;Maintaining facial identity (80-95% similarity)&lt;/li&gt;
&lt;li&gt;Creating authentic pixel art aesthetic&lt;/li&gt;
&lt;li&gt;Fast generation (10 seconds average)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's challenging:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very low-light photos&lt;/li&gt;
&lt;li&gt;Extremely complex scenes&lt;/li&gt;
&lt;li&gt;Photos where faces are tiny or obscured&lt;/li&gt;
&lt;li&gt;Multiple faces (focuses on largest)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We've tested thousands of photos, and the system achieves 80-90% average face similarity, with best cases hitting 95%+.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Want to see it in action? We've made it dead simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://pixagram.io" rel="noopener noreferrer"&gt;Pixagram.io&lt;/a&gt;&lt;/strong&gt; – Our full platform with blockchain integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://huggingface.co/spaces/primerz/pixagram" rel="noopener noreferrer"&gt;Hugging Face Space&lt;/a&gt;&lt;/strong&gt; – Try the AI without signup&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Hugging Face space lets you experiment with all the parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust identity preservation strength&lt;/li&gt;
&lt;li&gt;Control pixel art intensity&lt;/li&gt;
&lt;li&gt;Fine-tune depth and structure preservation&lt;/li&gt;
&lt;li&gt;Enable/disable color matching&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;We're not just building an AI art generator. We're building a &lt;strong&gt;Web3 social network&lt;/strong&gt; where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every post rewards creators&lt;/li&gt;
&lt;li&gt;Art lives forever on-chain&lt;/li&gt;
&lt;li&gt;No corporation owns your content&lt;/li&gt;
&lt;li&gt;Lightweight pixel art enables true decentralization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The NFT market has 11.6 million users worldwide, but most platforms are either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exciting but centralized&lt;/strong&gt; (like Instagram)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decentralized but boring&lt;/strong&gt; (like traditional NFT marketplaces)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pixagram aims to be both: &lt;strong&gt;exciting AND decentralized&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Deep Dive: The Code
&lt;/h2&gt;

&lt;p&gt;For the developers reading this, here's how the core generation works:&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="c1"&gt;# Core pipeline initialization
&lt;/span&gt;&lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StableDiffusionXLControlNetImg2ImgPipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_single_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;controlnet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;instantid_controlnet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth_controlnet&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;torch_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float16&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Face analysis
&lt;/span&gt;&lt;span class="n"&gt;faces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;face_app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;face_embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normed_embedding&lt;/span&gt;  &lt;span class="c1"&gt;# 512-dim
&lt;/span&gt;
&lt;span class="c1"&gt;# IP-Adapter projection
&lt;/span&gt;&lt;span class="n"&gt;image_embeds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;image_proj_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;insightface_embeds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Generation with dual ControlNets
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;input_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;control_image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;face_keypoints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth_map&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;controlnet_conditioning_scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;added_cond_kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_embeds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image_embeds&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;strength&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;num_inference_steps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;guidance_scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.45&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight? &lt;strong&gt;Multi-modal conditioning&lt;/strong&gt;. We're hitting the model from multiple angles simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text prompts guide style&lt;/li&gt;
&lt;li&gt;Depth maps preserve structure
&lt;/li&gt;
&lt;li&gt;Keypoints maintain facial geometry&lt;/li&gt;
&lt;li&gt;Embeddings preserve identity&lt;/li&gt;
&lt;li&gt;Img2Img keeps overall composition&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;We're currently in testnet alpha, with mainnet beta coming in October 2025. Our roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enhanced multi-face support&lt;/li&gt;
&lt;li&gt;More art styles beyond pixel art&lt;/li&gt;
&lt;li&gt;Advanced blockchain governance&lt;/li&gt;
&lt;li&gt;Creator monetization tools&lt;/li&gt;
&lt;li&gt;NFT marketplace integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Join the Revolution
&lt;/h2&gt;

&lt;p&gt;Whether you're a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developer&lt;/strong&gt; – Fork our code, build on our blockchain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artist&lt;/strong&gt; – Create pixel art that lives forever&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crypto enthusiast&lt;/strong&gt; – Early adopter advantages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curious human&lt;/strong&gt; – Just want to pixelate your selfie&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'd love to have you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it now:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Production platform: &lt;a href="https://pixagram.io" rel="noopener noreferrer"&gt;pixagram.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Experiment freely: &lt;a href="https://huggingface.co/spaces/primerz/pixagram" rel="noopener noreferrer"&gt;Hugging Face Space&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Get in touch: &lt;a href="mailto:omnibus@pixagram.io"&gt;omnibus@pixagram.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The internet promised to make information free and accessible forever. But in practice, links break, servers die, and companies disappear. Blockchain offers a second chance at that promise – but only if we can make it practical.&lt;/p&gt;

&lt;p&gt;Pixel art isn't just nostalgia. It's a 100x compression that makes permanent, decentralized storage actually feasible. It's small enough to embed in a blockchain, distinctive enough to be valuable as art, and our AI makes it accessible to everyone.&lt;/p&gt;

&lt;p&gt;That's the magic formula: &lt;strong&gt;AI accessibility + artistic value + blockchain permanence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Create artworks lasting forever on the blockchain while getting rewarded."&lt;/em&gt; That's not just our tagline – it's the future we're building.&lt;/p&gt;

&lt;p&gt;Come help us build it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What do you think? Would you want your photos turned into permanent blockchain pixel art? Let me know in the comments!&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #ai #blockchain #web3 #nft #pixelart #machinelearning #stablediffusion #opensource&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About Pixagram:&lt;/strong&gt;&lt;br&gt;
Pixagram SA is a Swiss company (Zug) developing Web3.0 social media infrastructure. Our technology combines AI art generation with lightweight blockchain storage, creating the first truly on-chain social network for pixel art NFTs.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>blockchain</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TurboSerial! High-Performance JS Serialization</title>
      <dc:creator>Matias Affolter</dc:creator>
      <pubDate>Tue, 02 Sep 2025 10:20:19 +0000</pubDate>
      <link>https://forem.com/matias_affolter/turboserial-high-performance-js-serialization-m70</link>
      <guid>https://forem.com/matias_affolter/turboserial-high-performance-js-serialization-m70</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A deep dive into &lt;a href="https://www.npmjs.com/package/@pixagram/turboserial" rel="noopener noreferrer"&gt;TurboSerial on NPM&lt;/a&gt;, a new JavaScript serialization library that outperforms MessagePack and CBOR through SIMD-inspired design, and why it might be your next choice for performance-critical applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the world of web development, especially in performance-critical applications, the way we handle data is paramount. Sending large JSON payloads can be a significant bottleneck. This is where binary serialization formats like &lt;strong&gt;&lt;em&gt;MessagePack&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;CBOR&lt;/em&gt;&lt;/strong&gt; have traditionally stepped in, offering more compact and faster alternatives.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;u&gt;But what if we could push the boundaries of performance even further? &lt;br&gt;
&lt;/u&gt;&lt;br&gt;
Enter &lt;strong&gt;&lt;em&gt;TurboSerial&lt;/em&gt;&lt;/strong&gt;, a new JavaScript serialization library designed from the ground up for extreme speed, inspired by modern, low-level CPU optimizations.&lt;/p&gt;
&lt;/blockquote&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.amazonaws.com%2Fuploads%2Farticles%2F25xpt0w11j67ej47b7nf.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.amazonaws.com%2Fuploads%2Farticles%2F25xpt0w11j67ej47b7nf.png" alt=" " width="800" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We ran a comprehensive benchmark suite of &lt;strong&gt;over 110 tests&lt;/strong&gt; comparing TurboSerial against the well-established MessagePack (v5) and CBOR (cbor-js). The results were eye-opening.&lt;/p&gt;

&lt;h2&gt;
  
  
  See For Yourself
&lt;/h2&gt;

&lt;p&gt;We believe in transparency and verifiable results. You can run the exact same benchmark suite in your own browser and see the performance difference firsthand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/Matias-Affolter/pen/bNVQLmN" rel="noopener noreferrer"&gt;Run the interactive benchmark&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2F7djxu0rjusjo6ut5a4qj.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.amazonaws.com%2Fuploads%2Farticles%2F7djxu0rjusjo6ut5a4qj.png" alt=" " width="800" height="1305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Verdict: Compatibility and Speed
&lt;/h2&gt;

&lt;p&gt;When it comes to handling the full spectrum of JavaScript types, the difference is stark. While the established libraries struggle with modern features like &lt;strong&gt;BigInt, complex Maps, and circular references&lt;/strong&gt;, TurboSerial handles them with ease.&lt;/p&gt;

&lt;p&gt;Compatibility is only half the story. In performance benchmarks, TurboSerial consistently outperformed the others, especially in scenarios involving large, structured data.&lt;/p&gt;

&lt;p&gt;For small and medium-sized JSON-like objects, TurboSerial was consistently the fastest. But its true power was revealed when handling large TypedArrays, where it was dramatically faster than the competition. This isn't magic; it's by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes TurboSerial So Fast?
&lt;/h2&gt;

&lt;p&gt;TurboSerial's performance advantage comes from architectural decisions inspired by cutting-edge, low-level libraries like simdjson. It leverages concepts that allow modern CPUs to process data in parallel.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. SIMD (Single Instruction, Multiple Data)
&lt;/h3&gt;

&lt;p&gt;At its core, SIMD is a CPU feature that allows a single instruction to be executed on multiple data points simultaneously.  Think of it as a multi-lane highway versus a single-lane road. Instead of processing one number at a time in an array, TurboSerial's SIMD-optimized routines can process blocks of 4, 8, or even more numbers in a single CPU cycle. This provides a massive throughput advantage for numeric arrays and TypedArrays.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Byte Alignment
&lt;/h3&gt;

&lt;p&gt;Modern CPUs are fastest when they can read data from memory addresses that are multiples of 4 or 8. Accessing misaligned data can cause the CPU to perform extra work, slowing down the entire process. TurboSerial is meticulous about aligning data in its internal buffers, ensuring that every read and write operation is as fast as the hardware allows.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Inspired by SIMD.js
&lt;/h3&gt;

&lt;p&gt;While the original SIMD.js specification was put on hold, its polyfills and the underlying "branchless" design philosophy were a major inspiration. By designing algorithms that avoid conditional branching (if/else) and instead process data in predictable blocks, TurboSerial minimizes CPU pipeline stalls, keeping the processor fed with data and operating at maximum efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with the API
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;TurboSerial maintains a simple and intuitive API, making it easy to drop into any project.&lt;/em&gt;&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="nx"&gt;TurboSerial&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@pixagram/turboserial&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;serializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TurboSerial&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Serialize any JavaScript value&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123456789012345678901234567890&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]),&lt;/span&gt;
  &lt;span class="na"&gt;typedArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Float32Array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.3&lt;/span&gt;&lt;span class="p"&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;serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;deserialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;serializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deserialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serialized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For power users, the library offers a rich set of configuration options to fine-tune its behavior for specific use cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advanced Configuration&lt;/strong&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TurboSerial&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;compression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// (Upcoming feature)&lt;/span&gt;
  &lt;span class="na"&gt;deduplication&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// Store duplicate objects/strings once&lt;/span&gt;
  &lt;span class="na"&gt;shareArrayBuffers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// Share ArrayBuffer references&lt;/span&gt;
  &lt;span class="na"&gt;simdOptimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// Enable SIMD-like optimizations for arrays&lt;/span&gt;
  &lt;span class="na"&gt;detectCircular&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;// Handle circular references&lt;/span&gt;
  &lt;span class="na"&gt;memoryPoolSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;         &lt;span class="c1"&gt;// Initial memory pool size in bytes&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While MessagePack and CBOR are excellent, established libraries, TurboSerial represents a step forward, leveraging modern hardware capabilities to offer superior performance and wider type compatibility. For applications where every millisecond and every data type counts, TurboSerial is a powerful new contender that is well worth considering for your serialization needs.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>algorithms</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The Dark Reality of NFTs: An Obscure and Limited Landscape</title>
      <dc:creator>Matias Affolter</dc:creator>
      <pubDate>Fri, 04 Oct 2024 14:50:04 +0000</pubDate>
      <link>https://forem.com/matias_affolter/the-dark-reality-of-nfts-an-obscure-and-limited-landscape-2ioc</link>
      <guid>https://forem.com/matias_affolter/the-dark-reality-of-nfts-an-obscure-and-limited-landscape-2ioc</guid>
      <description>&lt;p&gt;Non-Fungible Tokens (NFTs) have emerged as one of the most talked-about innovations in digital ownership, creativity, and technology. Yet, despite their widespread visibility, the world of NFTs remains shrouded in complexity, making them difficult to access for the majority of people. This article sheds light on the current constraints within the NFT ecosystem, highlighting the gaps between awareness and action, the gender disparities, and the overwhelming complexity of minting and acquiring NFTs. In the end, we’ll see why NFTs have yet to reach the mainstream and remain confined to niche circles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Crypto and NFTs are a path to financial independence, so it’s important that women and girls know about them. When I first heard about blockchain, I didn’t think it was for me. But I realized that it can be an inclusive space for women and people of color. I think crypto has the power to radically advance women’s rights.” – &lt;em&gt;Maliha Abidi, Artist &amp;amp; Author&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. &lt;strong&gt;Widespread Awareness but Minimal Engagement&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A Global Phenomenon Known by Many, Used by Few&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Surveys like those from &lt;strong&gt;Statista (2022)&lt;/strong&gt; show that NFTs are not lacking in awareness. Between &lt;strong&gt;40-50%&lt;/strong&gt; of internet users globally are aware of NFTs, representing hundreds of millions of people. Countries like the U.S., parts of Europe, and Asia (particularly Japan and South Korea) show even higher rates of awareness, often exceeding &lt;strong&gt;50%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, the critical issue lies in translating this awareness into action. Despite millions knowing about NFTs, only a small fraction actively engages with them. Fewer than &lt;strong&gt;1%&lt;/strong&gt; of those aware of NFTs have actually created or purchased one. This chasm between awareness and engagement points to deeper underlying problems, primarily related to technical barriers and the perceived complexity of the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Insight:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The widespread knowledge of NFTs doesn't translate into widespread action. Despite high awareness, a minuscule percentage of people are willing or able to engage due to perceived and real barriers.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. &lt;strong&gt;Creating NFTs: Technically Possible, Yet Unlikely&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Technical and Financial Barriers of Becoming a Creator&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While platforms like &lt;strong&gt;OpenSea&lt;/strong&gt; have streamlined the process of creating NFTs, the reality remains that fewer than &lt;strong&gt;3-5 million people&lt;/strong&gt; have ever minted an NFT, a figure that is tiny compared to the vast pool of individuals aware of the concept. Why such a low adoption rate? A few key reasons stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Technical Complexity&lt;/strong&gt;: Creating an NFT is not as simple as posting an image on Instagram. It involves understanding cryptocurrency wallets, gas fees, blockchain protocols, and other technical aspects, which are intimidating for newcomers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial Barriers&lt;/strong&gt;: Minting NFTs often incurs costs (gas fees on Ethereum, for example), which further limits participation to those willing to bear these expenses, unlike free-to-use platforms like social media.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Moreover, many NFT creation platforms lack the user-friendliness of everyday apps like &lt;strong&gt;LinkedIn&lt;/strong&gt; or &lt;strong&gt;Instagram&lt;/strong&gt;, further alienating the average user. The current NFT minting experience requires a familiarity with blockchain infrastructure that many people either do not possess or are unwilling to invest time to learn.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Insight:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Although it is technically possible to create NFTs, the process is overly complex and costly for the average internet user, making the barrier to entry significantly higher than on mainstream platforms.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;strong&gt;Acquiring NFTs: A Gendered and Imbalanced Landscape&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Gender Divide in NFT Ownership&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While about &lt;strong&gt;15-20 million&lt;/strong&gt; people globally have purchased or own NFTs, the ownership landscape is notably skewed in terms of gender. Only about &lt;strong&gt;1 in 4 NFT holders&lt;/strong&gt; are women, which points to a significant gender imbalance in the space. This statistic is troubling when considering the potential for NFTs to democratize digital ownership and creativity across demographics.&lt;/p&gt;

&lt;p&gt;This imbalance isn't just about who is buying NFTs; it's also about who feels welcomed and capable within the NFT ecosystem. Many women report feeling alienated or underserved by current platforms, which cater more to male tech enthusiasts and crypto investors.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Buyers Outnumber Creators, But Complexity Remains&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There are roughly &lt;strong&gt;four times more buyers than creators&lt;/strong&gt; in the NFT space, but even becoming a buyer comes with its own challenges. For someone unfamiliar with cryptocurrencies, acquiring an NFT can feel unnecessarily complicated, with steps that require setting up a digital wallet, purchasing crypto, navigating decentralized platforms, and managing security risks. This isn’t as simple as making a purchase on Amazon or posting on a social media platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Insight:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Gender disparity in NFT ownership and the complex process of purchasing an NFT further limit the democratization of this technology, alienating both potential creators and buyers alike.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. &lt;strong&gt;Platform Constraints and Narrow Use Cases&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;NFT Platforms Are Not Mainstream-Friendly&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Despite the potential of NFTs, the platforms that support them remain niche. &lt;strong&gt;OpenSea&lt;/strong&gt;, &lt;strong&gt;Rarible&lt;/strong&gt;, and &lt;strong&gt;Foundation&lt;/strong&gt; dominate the space, but they are complex, highly specialized, and cater to a specific subset of tech-savvy individuals. While social media platforms like &lt;strong&gt;Instagram&lt;/strong&gt; and &lt;strong&gt;LinkedIn&lt;/strong&gt; could potentially open the doors for wider NFT adoption, they do not currently offer easy integration for NFTs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Limited Functionality Restricts Use Cases&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Even for those who do engage, the use cases for NFTs remain limited. Most NFTs are centered around digital art and collectibles, with very few use cases in mainstream or practical scenarios that would appeal to the average person. As a result, the audience is confined to collectors, artists, and crypto enthusiasts, leaving broader applications largely untapped.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Key Insight:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;NFT platforms, as they exist today, cater to a very specific, niche audience. Their functionality and user experience are nowhere near the simplicity of mainstream platforms like Instagram or LinkedIn, limiting the potential for broader adoption.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: &lt;strong&gt;The Unseen Obstacles Hindering NFTs’ Mainstream Adoption&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The NFT space, though promising, is still mired in obscurity, complexity, and imbalance. While millions are aware of NFTs, very few are able or willing to engage with them. The barriers to entry, whether through creation or acquisition, are too high for most, and the platforms that dominate the space are inaccessible to the average internet user. Furthermore, gender disparities persist, highlighting the fact that the NFT ecosystem is far from inclusive.&lt;/p&gt;

&lt;p&gt;To unlock the full potential of NFTs, platforms must simplify the user experience, eliminate financial and technical barriers, and widen the use cases beyond digital art and collectibles. Without these changes, NFTs will remain a niche technology, overshadowed by the overwhelming complexity that defines it today.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Statista, &lt;strong&gt;Global NFT Awareness Survey (2022)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;NonFungible.com, &lt;strong&gt;NFT Ecosystem Report (2022)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cryptocurrency</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>🚀 Introducing LacertaDB: A Simple and Powerful JavaScript Database</title>
      <dc:creator>Matias Affolter</dc:creator>
      <pubDate>Thu, 03 Oct 2024 08:06:09 +0000</pubDate>
      <link>https://forem.com/matias_affolter/introducing-lacertadb-a-simple-and-powerful-javascript-database-2j7c</link>
      <guid>https://forem.com/matias_affolter/introducing-lacertadb-a-simple-and-powerful-javascript-database-2j7c</guid>
      <description>&lt;p&gt;I’m excited to introduce &lt;strong&gt;LacertaDB&lt;/strong&gt;, a new database I’ve designed that’s &lt;strong&gt;simple&lt;/strong&gt;, &lt;strong&gt;flexible&lt;/strong&gt;, and &lt;strong&gt;powerful&lt;/strong&gt;. It's still evolving, but even now, it brings some unique capabilities to the table that I think you'll find fascinating. &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.amazonaws.com%2Fuploads%2Farticles%2Fmcg9opx5pyjda6vhfxii.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.amazonaws.com%2Fuploads%2Farticles%2Fmcg9opx5pyjda6vhfxii.png" alt="LacertaDB Javascript Logo" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me walk you through what makes &lt;strong&gt;LacertaDB&lt;/strong&gt; so interesting:&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Key Features:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Effortless Compression &amp;amp; Encryption&lt;/strong&gt;:
Simply by setting the properties &lt;code&gt;_compressed&lt;/code&gt; or &lt;code&gt;_encrypted&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;, the &lt;strong&gt;Document&lt;/strong&gt; class automatically recognizes the need to compress or encrypt your data. No extra effort required on your part! It handles both packing and unpacking seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports Various Data Types&lt;/strong&gt;:
Thanks to &lt;strong&gt;joyson&lt;/strong&gt;, you can pack any type of JavaScript data into &lt;strong&gt;LacertaDB&lt;/strong&gt;—from &lt;code&gt;TypedArray&lt;/code&gt;, to &lt;code&gt;Errors&lt;/code&gt;, and everything JSON supports as well.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Metadata Storage with LocalStorage&lt;/strong&gt;:
What makes &lt;strong&gt;LacertaDB&lt;/strong&gt; architecturally unique is that it uses &lt;strong&gt;localStorage&lt;/strong&gt; to store metadata for each database, even when multiple collections exist. Though &lt;strong&gt;localStorage&lt;/strong&gt; is capped at 5MB, that’s &lt;strong&gt;plenty for metadata&lt;/strong&gt;.
Here’s what we keep track of:

&lt;ul&gt;
&lt;li&gt;📏 &lt;strong&gt;Length&lt;/strong&gt; of documents&lt;/li&gt;
&lt;li&gt;🆔 &lt;strong&gt;IDs&lt;/strong&gt; of documents&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;Sizes&lt;/strong&gt; of documents&lt;/li&gt;
&lt;li&gt;🛡️ &lt;strong&gt;Permanence&lt;/strong&gt; (&lt;code&gt;_permanent&lt;/code&gt; property ensures documents don't get deleted during auto-compaction)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This approach allows &lt;strong&gt;LacertaDB&lt;/strong&gt; to quickly retrieve the &lt;strong&gt;database state&lt;/strong&gt; and &lt;strong&gt;automatically compact&lt;/strong&gt; the database without querying &lt;strong&gt;IndexedDB&lt;/strong&gt;—which, while fast, isn’t as speedy as &lt;strong&gt;localStorage&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 The Inner Workings
&lt;/h2&gt;

&lt;p&gt;While &lt;strong&gt;LacertaDB&lt;/strong&gt; needs a bit more work, it already performs &lt;strong&gt;remarkably well&lt;/strong&gt;. You can easily pack and unpack hundreds of documents, whether compressed, encrypted, or not, within &lt;strong&gt;milliseconds&lt;/strong&gt;! 🚀&lt;/p&gt;

&lt;p&gt;And all of this while managing metadata in a lightweight manner and avoiding unnecessary overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Why Use LacertaDB?
&lt;/h2&gt;

&lt;p&gt;If you're looking for a &lt;strong&gt;simple-to-use database&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports &lt;strong&gt;any type of JavaScript object&lt;/strong&gt; 🛠️&lt;/li&gt;
&lt;li&gt;Handles data compression/encryption with a single property change 🔒&lt;/li&gt;
&lt;li&gt;Allows you to easily manage collections using instance methods 📁&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then &lt;strong&gt;LacertaDB&lt;/strong&gt; might just be what you need! &lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ How to Use It
&lt;/h2&gt;

&lt;p&gt;You can get started by installing it from npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;lacertadb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example usage:&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="nx"&gt;LacertaDB&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lacertadb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a database instance and get a (new) collection&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LacertaDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myDatabase&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;coll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;documents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Add a document with encryption and compression&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;_compressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;_encrypted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some sensitive data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Display the query result (you'll see it's encrypted)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Display the document as original&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🔍 &lt;strong&gt;Want to know more?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Check out the &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/lacertadb" rel="noopener noreferrer"&gt;NPM package&lt;br&gt;
&lt;/a&gt;&lt;/strong&gt; or start using &lt;strong&gt;LacertaDB&lt;/strong&gt; in your projects today. Feedback and contributions are always welcome!&lt;/p&gt;

&lt;p&gt;If you’ve ever thought, “I just need a &lt;strong&gt;simple&lt;/strong&gt; database to store my JavaScript objects,” look no further. &lt;strong&gt;LacertaDB&lt;/strong&gt; is here to make your life easier. 🎉&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Code is like humor. When you have to explain it, it’s bad.”&lt;/strong&gt; – Cory House&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Give &lt;strong&gt;LacertaDB&lt;/strong&gt; a try, and see how it fits into your next project! 🙌&lt;/p&gt;




&lt;p&gt;This database is evolving, but with its ability to &lt;strong&gt;compress&lt;/strong&gt;, &lt;strong&gt;encrypt&lt;/strong&gt;, and &lt;strong&gt;handle various data types&lt;/strong&gt; in &lt;strong&gt;milliseconds&lt;/strong&gt;, I believe it’s a solid choice for projects that need a &lt;strong&gt;lightweight and flexible&lt;/strong&gt; storage solution. 🚀&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>database</category>
      <category>npm</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
