Engineering
Data
Overengineering, type-safe nightmares, and the occasional switch statement.
Feb 14, 2025
Hello Querio users (present and future)! My name’s Nikolay. You might know me as a guy who spent the last 3 years writing portfolio management software in .NET or from that time my project supervisor at university commented on my intelligence. I tricked Querio team into hiring me three short weeks ago. And look, I am not going to sit here and pretend like I have anything actually insightful to tell you. No, I am taking it all the way back to 2006 LiveJournal (I was 8 years old) and share with you my subjective experience of doing my new job.

Challenge accepted.
You might think I'm making this up—I'm not. And while you may question my intelligence (the jury's still out on that one), this is genuinely what happens when you leave the safe harbor of enterprise software, where everything is Properly Architected™, and bellyflop into the world of early-stage startups.
Coming from enterprise, I can still feel new neural connections forming in previously untouched regions of my brain. Now here I am, witnessing the aftermath of Cursor's "AGI moments" scattered throughout version control (and to be fair, some of them come close). After years of change requests breaking my soul, I wonder if moving fast and breaking things might just break me faster.

hot take: js database tooling

I'd tell you to brace for controversy, but let's be honest - we're all thinking it.
During the last platform shift something happened. Like many others, I joined the fold when JavaScript was becoming the universal runtime - browsers, servers, mobile apps, smart kettles, you name it. I managed to get a job writing C# and watched from the sidelines as my peers any% speed-ran decades of architecture patterns, reinventing and reimagining them for this new stack.
Supply has followed demand. Dev-tools companies raised millions of dollars and used it to put on a decade-long magic show with only ORMs on stage and all of us in attendance.
With a flourish of a handkerchief, each covered the unruly databases. "Watch closely," they whispered, lifting the silk with practiced grace to reveal... ta-da! A pristine API with three or four meticulously documented endpoints. The audience gasped—all those tables and joins had vanished, replaced by GET, POST, and DELETE operations. The N+1 queries giggled and slipped behind the curtain.
Somewhere along the way we collectively decided that writing SQL was passé. I admit, SQL queries don't exactly fit in or around your JSX or anywhere inside the virtual DOM. Don’t know about you, but I am already stuck in a messy relationship with JS, markup and Tailwind classes, and SQL is definitely not invited to that party.
Imagine:
…hmmm doesen’t look half bad!

the tale of two ORMs

Here's a sentence I never thought I'd write: we use Prisma for writes and Drizzle for reads (ish). I know what you're thinking - "that's insane!" And you're right! But here's the twist: it works.
Like any good JS library, both sit there like WWE heavyweight champions, demanding endless boilerplate tributes and infinite config file homages before releasing your data. Sure, Prisma's mutations are sweet, the type safety is solid, and the schema management is chef's kiss. Thank you Prisma! But what's with the N+1 query for every relation unless explicitly included? Come on Prisma... And rolling back migrations? Hope you enjoy doing that by hand. Really, Prisma?
But let's be real, if I really cared about redundant queries, I wouldn't have 14 Claude tabs open. We face different challenges. In our monorepo, we follow the workspace pattern. We've got a Node server running Express that periodically pokes your database for context, alongside a hefty Next.js app doing its thing. Now we want to share our lovely Prisma queries and mutations with our server—but we can't! The prisma
(generated) client must be lifted out of the Next app, repackaged, dropped at the top level, and reimported. Congratulations, you now get to juggle two different binary generations—assuming you've managed to untangle the package mess.
And I know what you're thinking—"just put all the Prisma code in your Express server and call it a day." Good idea! Stay tuned for that.
Anyway. We couldn't share Prisma between our two apps. May be a skill issue. Enter: Drizzle. It's runtime agnostic - no binary engines, no platform-specific code generation, just TypeScript that runs anywhere. Want to share your database layer between workspaces? It's just code - bundle it, import it, done. The queries are just SQL wrapped in a type-safe builder, so there's no magic to break when you move between environments.
The bundle size is tiny compared to Prisma's big chungus binaries. Not that this makes a difference for us today...
But it’s not all drizzle and rainbows (heh). The migrations story isn't exactly making me write home. The CLI tools are in perpetual beta, and don't get me started on trying to maintain separate migration paths for different environments.
But here's the kicker - Drizzle, or any other ORM promising smaller bundles, perfect type safety, and world peace all have one big flaw. They just ain’t inside our app! And the effort of ripping Prisma out and putting another ORM in I’d rather spend on the roadmap.
And yes I have been drinking DHH Kool-Aid and building all my own projects in Rails and ActiveRecord
. The ORM situation in our JS today feels like I traded in my good-ol Prius for a two-headed dragon - it's powerful, but really scary and don’t talk to me about insurance premiums.

me vs typescript type system

Querio takes in your natural language prompts and writes SQL and Python to wrangle and visualise data for you while you’re scrolling TikTok Shop.
Users want to see the source data for their charts. What users don’t know is that we send their charts back as Plotly objects over the wire and we have only a modicum of an idea of what the chart actually is until we render it. I needed to build a chart-to-table toggle (maybe my uni professor was onto something).

There it is on the left!
When I first heard my assignment my reptilian C# brain hissed: “pattern matching”. I never made much use of higher brain function so what I did next led to the most bloody, gory and senselessly violent battle with TypeScript's type system in recorded history. I very narrowly escaped death but emerged victorious.
In the technical spirit of this article, I will let the code do the talking. I was frustrated that I had to type discriminant string by hand instead of having them IntelliSensed into the function, so I wrote
I thought to myself: “there is a profound insight about type theory hiding in there”. You could use my ‘pattern matching’ like this.
Patent pending.
I was done. I proudly wound my neck back inline with my spine, feeling fiercely intelligent. When I left the office at 22:34 on a Friday I texted my friend about my elegant extension to the language.
When I got home I realised I could have written:
...and gotten the exact same type safety without conjuring an eldritch horror of generic constraints. Sometimes you can move so fast that you build an entire type-safe pattern matching framework just to appreciate a switch
statement.
Whew! Time flies when you’re having fun! I am way over the word-limit and I haven’t even talked about the new agent architecture or Pedro’s new fully-websocketed Querio Explore Page that rips harder than Vector W8 Twin Turbo by Vector Aeromotive (1989-1993).
For next month’s issue of nik’s devlog I can promise takes on:
deploying Javascript
gross ORM misuse
???
nik@querio.ai if you have any ideas about any of the above or just want to fight me about type-guards.