Context Window Management as a Database: Ask for 12,000 Tokens, Get the Most Useful Ones
An agent is ninety tool calls into a refactor. Step 12 was a grep that returned 52 KB, and all of it is still in the prompt. The user’s instruction from step 1, “never touch db/migrations”, fell out of the window ten steps ago, because the framework drops the oldest messages first. The agent edits a migration. Nothing malfunctioned; the truncation rule did exactly what it was written to do.
Cron for AI Agents: Schedules, Timeouts, Overlap Rules and Cost Ceilings in One Config File
A nightly agent job triages new issues. One night an issue arrives with a 400 KB log attached. The agent reads it, a tool call fails, the agent retries, and the loop runs until the month’s token budget is gone. Meanwhile cron, which has no idea what a token is, starts the next run on schedule. Now two copies are fighting over the same issue tracker.
Cron was built for jobs that cost nothing, finish in seconds and do the same thing every time. Agent jobs cost money per token, run for an unpredictable time and can loop. The useful ones are still boring and periodic: summarize what changed in a repo since yesterday, triage new issues each morning, check a competitor’s pricing page weekly. What they need is a scheduler that stays as small as cron and adds four things: a cost ceiling, a timeout that actually kills, an overlap rule, and state carried between runs. Anything past that is an orchestration platform, a different and much larger product.
Database-to-Database Sync for Local-First Apps Lives or Dies on Conflict Rules
Take a field technician who edits a work order on a tablet in a basement with no signal. Upstairs, the office edits the same order from a desk. Both hit save at 10:42 by their own clocks, and one of those clocks is ninety seconds off. When the tablet finds a signal, the sync layer has to produce one order that both people can live with. That decision is the product. Offline-first apps are harder than they look, and a large share of the difficulty sits in this one step.
Debug From a Timeline of State Changes Instead of Ten Thousand Log Lines
A ticket comes in: order 8812 shows as cancelled, but the customer’s card was charged. You open log search. The checkout service wrote a couple of hundred lines for that request; the payment webhook handler wrote a few dozen; the job that expires unpaid orders wrote a line for every order it looked at that minute. The answer is in there somewhere. Forty minutes later you find it. The expiry job cancelled the order thirty seconds after checkout began, and the payment provider’s webhook landed half a second after that.
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.