DuckDB Already Queries Every File in a Folder, So Build the Part That Infers the Joins
Someone hands you a zip: customers.csv from the CRM, a JSON dump from the billing API, and a SQLite file from an internal app nobody has touched in two years. DuckDB will make all three queryable in a few lines of SQL, with no import step (SELECT * FROM 'customers.csv' works as written). Then you spend the afternoon working out which column joins to which. The CRM says customer_id and stores 00123. The billing API says customerId and stores 123. The SQLite table has a column called customer holding the text 123. Same customer, three spellings.
Embedded Vector Search Is Crowded: What a One-File Vector Database Needs to Stand Out
You have 40,000 support articles and an app that should offer “similar articles”. Embedded at 768 dimensions in float32, that’s 40,000 × 768 × 4 bytes, about 123 MB of vectors. The standard advice is to stand up a vector database: a service, a port, credentials, a client library and a backup story for 123 MB. A file would do.
Below a few million vectors the server is the overhead, which is why the embedded field filled up fast. So the useful question is what a newcomer brings that the free libraries don’t. My answer is one sharp edge you can state in a sentence, plus measurements the others leave you to make yourself.
Facts Should Expire: A Database That Tells an AI Agent When Its Knowledge Has Gone Stale
An agent keeps a memory table, and two rows matter for today’s task: a supplier’s headquarters city, written eleven months ago, and a freight quote, written three hours ago. A SELECT returns both in the same shape. The headquarters is probably still right. The quote may already be wrong. Nothing in either row says so, and the agent repeats both in the same flat tone.
A row has no idea how old its truth is. It might carry a created_at, and a careful person can compute an age from it, but the decay rate belongs to the kind of fact, not to the table. A three-week-old headquarters address is fine. A three-week-old shipping rate is fiction. Server health goes bad in half a minute. No timestamp column holds that knowledge, and nothing forces a query to read it anyway.
Give Every Database Query a Budget and Fail the Build When It Scans Too Much
A developer changes a login lookup to WHERE lower(email) = lower($1) so that sign-in stops being case-sensitive. Every test passes. The btree index on email can’t serve a query that wraps the column in a function, so Postgres reads the whole users table, and on a test database with forty rows that’s the cheapest plan anyway. The change ships. A week later someone notices login latency tracking the signup count. The fix is a one-line expression index that would have taken a minute if anything had objected during review.
Group Errors by Behavioral Signature Instead of Stack Trace Text
Add six lines to the top of a file and ship it. Every stack trace through that file now carries different line numbers, so a tracker that hashes the trace files a bug it has seen a hundred times as a brand-new issue. Meanwhile an older issue titled TimeoutError has collected comments from people who each fixed a different timeout and wondered why it never closed.
Grouping fails in both directions at once. One bug turns into hundreds of issues because the message embeds an order ID, the line numbers moved, or a framework upgrade changed the frames in the middle. Two bugs turn into one because every timeout in the codebase raises the same exception type from the same retry helper.
Incremental View Maintenance Small Enough to Embed Turns Dashboard Queries Into Lookups
A dashboard tile shows today’s US traffic, so every page load runs SELECT count(*) FROM events WHERE country = 'US' over a table that grew by a few hundred thousand rows since yesterday. SQLite answers correctly. It also walks every matching index entry to do it, because its b-trees don’t keep counts, and it does the same walk for the next viewer and the one after. Between two page loads the answer moves by a handful of rows, yet each load pays for all of them.
Kafka for One Machine: An Embedded Event Log With Offsets, Compaction and No Broker
A desktop app wants an undo history that survives a crash. An edge gateway buffers sensor readings while its uplink is down and has to replay them, in order, once the link is back. An AI agent writes down every action it takes so a bad run can be replayed later. All three are the same data structure: an append-only sequence of records, plus readers that remember where they stopped. Kafka is that structure, and also a cluster, partitions and the people who tune them.
Mapping Every Dependency to the Features That Break If It Disappears Tomorrow
Run npm ls --all on a mid-sized web app and you get a tree that scrolls for pages. It’s accurate and complete, and on the morning a maintainer deletes a package it tells you almost nothing. You can see that tiny-util sits three levels down. You can’t see whether losing it breaks the checkout page or a script nobody has run since spring.
A dependency tree answers “what do I depend on”. The question that matters is “what breaks, and for whom, if this package vanishes or turns hostile”. They need different data. The tree comes from a lockfile. The answer comes from your own source: which functions call the package, which routes, commands and jobs those functions serve, and how much code would change to replace it. A tool that produced that for every package would turn dependency management from an inventory into something a product owner can read.
Most Log Volume Is a Few Templates Repeated, So Reduce Logs Locally Before Shipping Them
Take a day of production logs from one service, mask the numbers, IDs and quoted strings in every line, and sort the resulting patterns by how often they occur. The top of that list is short and dull: health checks, cache hits, a retry notice from a client library nobody owns. Each of those lines was serialized, shipped, parsed and indexed millions of times to say the same thing, and you paid for every copy. Run it on your own logs. The claim is easy to check, so don’t take it on faith.
One Binary, One File, No Daemon: The SQLite and nginx Pattern as a Product Strategy
Compare two quickstarts. The first says to install Docker, bring up a compose file with a database, a cache and a worker, create an account, and paste a token into an env file. The second says to download one file and run it. Both tools might solve the same problem. Only one of them survives an evaluation that lasts ten minutes.
The second quickstart is a product decision, made in the architecture. SQLite and nginx made it decades ago, and Caddy, DuckDB, ripgrep, jq and Hugo have made it again in their own corners. Small surface area, few dependencies and one artifact to copy work as an adoption strategy. For a one-person or AI-assisted project they also work as the only scope control that holds up. That’s the claim, and the rest of this post tries to break it.