Prompt injection is the defining security problem of LLM applications, and — unlike SQL injection, which it superficially resembles — it has no clean fix. The reason is structural: a language model reads instructions and data through the same channel, and cannot reliably tell which is which. This opening post explains why that makes injection fundamentally hard, and reframes the goal from "prevent it" to "contain the blast radius."
Prompt injection is the defining security problem of LLM applications, and unlike SQL injection it has no clean fix — because a model reads instructions and data through the same channel and can't reliably tell them apart. This opening post explains why that makes injection fundamentally hard, and reframes the goal from prevent to contain the blast radius.
The final decision isn't "which algorithm is best" — it's "which point on the recall-latency-memory triangle does my workload need, and what's the simplest thing that hits it." For a huge number of systems the honest answer is far less exotic than the vector-database marketing suggests, and knowing when you've genuinely outgrown Postgres is worth more than knowing HNSW's internals.
The final decision isn't 'which algorithm is best' — it's 'which point on the recall-latency-memory triangle does my workload need, and what's the simplest thing that hits it.' Often the honest answer is far less exotic than the vector-database marketing suggests.
SQL is a language where you say what you want, not how to get it — and the component that invents the "how" is the query planner, the closest thing a database has to a brain. When a query is mysteriously slow, the answer is almost always in the plan, which is why reading `EXPLAIN` is the single most valuable database skill you can learn.
SQL says what you want, not how to get it — and the component that invents the 'how' is the query planner, the closest thing a database has to a brain. Reading EXPLAIN is the single most valuable database skill you can learn.
The vector-storage decision has a boringly practical answer that cuts against the hype: for most systems, the database you already run with a vector extension beats adding a new specialized system — until scale or specific features force the upgrade.
A boringly practical answer that cuts against the hype: for most systems the database you already run with a vector extension beats adding a specialized system — until scale or specific features force the upgrade.
The reason a long analytics query doesn't block every writer in your database — and vice versa — is a single elegant idea: never overwrite data, keep multiple versions, and give each transaction a consistent snapshot in time. MVCC is how nearly every modern database delivers isolation without readers and writers fighting over locks.
The reason a long analytics query doesn't block every writer — and vice versa — is a single elegant idea: never overwrite data, keep multiple versions, and give each transaction a consistent snapshot in time. That's MVCC.
Dependency injection is the least flashy Pydantic AI feature and quietly one of the most important — it's what lets your agents reach real databases, API clients, and user context without hard-wiring them, and it's the single biggest reason Pydantic AI agents are so testable. Borrowed straight from how good backend frameworks work, applied to agents.
Dependency injection is the least flashy Pydantic AI feature and quietly one of the most important — it lets agents reach real databases and clients without hard-wiring them, and it's the single biggest reason Pydantic AI agents are so testable.
A transaction is a promise that a group of operations happens all-or-nothing and doesn't get corrupted by everyone else doing the same thing at once. Most developers know the word ACID; far fewer know that the "I" — isolation — is a dial with several settings, and that the default setting in most databases allows anomalies they've never heard of.
Most developers know ACID; far fewer know that the 'I' — isolation — is a dial with several settings, and that the default in most databases allows anomalies they've never heard of.
Replication makes copies of the whole dataset; partitioning splits the dataset into pieces so each node holds only some of it. Every large-scale system does both — and the way you choose which piece goes where quietly determines whether your load spreads evenly or one unlucky node melts down under a celebrity's traffic.
Partitioning splits a dataset into pieces so each node holds only some of it. How you choose which piece goes where decides whether load spreads evenly or one unlucky node melts down under a celebrity's traffic.
HNSW is the algorithm behind most modern vector databases, and its idea is borrowed from the "six degrees of separation" that connects any two people through a short chain of acquaintances. Build the right graph of vectors, and you can walk from a random entry point to a query's nearest neighbors in a handful of hops — searching millions of vectors while touching only a few hundred.
HNSW is behind most modern vector databases, and its idea comes from the 'six degrees of separation' that connects any two people through a short chain — build the right graph and you can walk from a random entry to a query's nearest neighbors in a handful of hops.
An index is a data structure that lets a database find rows without reading the whole table — the difference between flipping to a book's index and reading every page. It's the highest-leverage performance tool a database gives you, and also the most misused: every index you add speeds up reads and slows down writes, so the skill is knowing exactly which ones earn their cost.
An index lets a database find rows without reading the whole table — the highest-leverage performance tool a database gives you, and the most misused: every index speeds up reads and slows down writes.
Replication is keeping copies of the same data on multiple nodes, and it's the answer to two different problems at once — surviving failures and serving reads at scale. The hard part is never the copying; it's what happens when the copies disagree, which they always eventually do.
Replication keeps copies of data on multiple nodes to survive failures and scale reads. The hard part is never the copying — it's what happens when the copies disagree, which they always eventually do.
An agent without tools can only think and write; tools are what let it act — search the web, query a database, call an API — and turning a Python function into a CrewAI tool is deliberately almost effortless.
An agent without tools can only think and write; tools are what let it act — search the web, query a database, call an API — and turning a Python function into a CrewAI tool is deliberately almost effortless.
Durability — the promise that a committed transaction survives a crash — comes down to one deceptively simple rule: write down what you're about to do before you do it. The write-ahead log is that rule made concrete, and it's the reason a database can be both fast and crash-safe, two goals that otherwise pull in opposite directions.
Durability comes down to one deceptively simple rule: write down what you're about to do before you do it. The write-ahead log is that rule made concrete — the reason a database can be both fast and crash-safe.
The buffer pool is where a database spends most of its memory and wins or loses most of its performance. It's a cache of disk pages in RAM, and the difference between a query that hits it and one that misses is the difference between a microsecond and a millisecond — a thousandfold gap that decides whether your database feels fast.
The buffer pool is where a database spends most of its memory and wins or loses most of its performance — a cache of disk pages in RAM, where a hit versus a miss is a thousandfold latency gap.
The CAP theorem is the most cited and most misunderstood result in distributed systems. It does not say "pick two of three." It says something narrower and more useful: when the network partitions, you must choose between consistency and availability — and PACELC completes the picture by asking what you trade even when it doesn't.
The CAP theorem doesn't say 'pick two of three.' It says that during a partition you must choose consistency or availability — and PACELC completes it by asking what you trade even when the network is healthy.
Almost every database on earth stores its data in one of two structures: a B-tree that updates in place, or an LSM-tree that only ever appends. This one choice ripples through everything — read speed, write speed, space usage, and latency predictability — so knowing which your database uses tells you more about its behavior than almost anything else.
Almost every database stores data in one of two structures: a B-tree that updates in place, or an LSM-tree that only appends. This one choice ripples through read speed, write speed, space, and latency predictability.
A consistency model is a contract between a distributed system and its users about what a read is allowed to return. It sounds abstract until you realize that every replication bug, every "why did my write disappear?" incident, and every heated architecture debate is really an argument about which model you're entitled to.
A consistency model is a contract about what a read is allowed to return. Every replication bug and 'why did my write disappear?' incident is really an argument about which model you're entitled to.
Retrieval is how you put external, current knowledge into a model's window, and doing it well is a context-engineering problem — the goal is not the most documents, but the right ones.
Retrieval is how you put external, current knowledge into a model's window, and doing it well is a context-engineering problem — the goal is not the most documents, but the right ones.
Every RAG system, recommendation engine, and semantic search box rests on one deceptively simple operation: given a query vector, find the closest vectors among millions. Doing it exactly is easy and doesn't scale; doing it fast enough to be useful means giving up exactness on purpose — and understanding that trade is the foundation of vector search.
Every RAG system and semantic search box rests on one operation: given a query vector, find the closest among millions. Doing it exactly is easy and doesn't scale; doing it fast means giving up exactness on purpose — and that trade is the foundation of vector search.
A database is not magic — it's a program that turns your rows into bytes on a disk and finds them again quickly, correctly, and without losing them when the power fails. Understanding the machine underneath the SQL is what separates someone who writes queries from someone who knows why they're slow.
A database is a program that turns your rows into bytes on a disk and finds them again quickly, correctly, and without losing them when the power fails. Understanding the machine underneath the SQL is what separates writing queries from knowing why they're slow.
The Model Context Protocol lets Claude Code reach beyond your codebase — into your databases, issue trackers, docs, and services — through a standard, pluggable interface.
The Model Context Protocol lets Claude Code reach beyond the codebase into databases, trackers, docs, and services through a standard interface — what MCP is, how to connect servers, and treating each server as a least-privilege trust decision.
Choosing and scaling the data layer without cargo-culting: how to pick relational versus NoSQL by access pattern, why every index is a tax on writes, and why your shard key is the highest-stakes decision you will make.
Choosing and scaling the data layer: relational vs NoSQL by access pattern, indexing (B-tree/hash/LSM), normalization vs denormalization, replication, partitioning/sharding and the shard-key decision, and the distributed-transaction trade-off.
Two tightly-linked OWASP LLM risks that turn a clever prompt injection into real-world damage — and the Python patterns that shrink the blast radius: treat model output as untrusted input, and give agents the least agency they can get away with.
Two OWASP risks that turn an injection into damage: insecure output handling (model output is untrusted input — never eval/shell/SQL it unescaped) and excessive agency (least-privilege tools, allow-lists, human approval for irreversible actions, audit logs).
Two systems will drift. The transactional outbox stops you losing events; reconciliation is how you find the truth when they disagree anyway.
You can't atomically update your database and publish a message. The transactional outbox (or CDC) stops you losing events; reconciliation is how you find and classify the breaks when two systems drift anyway.
C is fifty years old and still runs the world — operating systems, databases, language runtimes, embedded devices, and the standard libraries under almost everything else. Learning C is learning how computers actually work: memory, pointers, and the thin layer between your code and the machine. This series builds C from the ground up, and it starts with what C is and what really happens when you compile it.
C is fifty years old and still runs the world — operating systems, databases, language runtimes, embedded devices. Learning C is learning how computers actually work: memory, pointers, and the thin layer between your code and the machine. This series builds C from the ground up, starting with what C is and what really happens when you compile it.
The same data can be organized in ways that make analytical queries fast, intuitive, and cheap — or slow, confusing, and expensive. Data modeling is the craft of that organization, and it's where a counterintuitive truth lives: the careful normalization that's correct for application databases is often exactly wrong for analytics. Analytical data wants to be shaped differently, around how questions are asked rather than how data is written, and understanding dimensional modeling is understanding how to make a warehouse actually usable.
The same data, organized differently, makes analytical queries fast and intuitive — or slow and confusing. Data modeling is the craft of that organization, and it holds a counterintuitive truth: the normalization that's correct for application databases is often exactly wrong for analytics.
"Just put it in a database" stops working the moment you're dealing with analytics at scale — because the database that runs your application is optimized for exactly the wrong thing. Analytical data needs different storage: systems built to scan and aggregate huge volumes, not to serve fast individual transactions. The landscape of analytical storage — data warehouses, data lakes, and the newer lakehouses — is where data engineering decisions about where data lives get made, and understanding the differences (starting with OLTP vs OLAP) is essential.
'Just put it in a database' stops working the moment you're doing analytics at scale — the database that runs your app is optimized for exactly the wrong thing. Analytical data needs different storage: warehouses, lakes, and lakehouses. Understanding the differences (starting with OLTP vs OLAP) is essential.
How to serialize an agent.Session to disk and resume it later, so a follow-up prompt still remembers earlier turns across a process restart.
An agent.Session serializes with encoding/json, so you can marshal it to disk or a database and resume it later with the model still remembering earlier turns.
Knowing to cache is one thing; wiring the cache into your application correctly is another. Should the application manage the cache itself, or should the cache sit transparently in front of the source? Should writes go to the cache, the database, or both — and in what order? These questions have standard answers — the caching patterns — and choosing the right one shapes your consistency, performance, and complexity. Getting the pattern right is how caching goes from "store some stuff" to a coherent, correct design.
Knowing to cache is one thing; wiring the cache into your application correctly is another. Should the application manage the cache itself, or should it sit transparently in front of the source? Should writes go to the cache, the database, or both? These questions have standard answers — the caching patterns.
PostgreSQL row-level security as HIPAA defence in depth. Why fail-open application filtering isn't enough, and how 'append-only at DB GRANTs' carries more of the §164.312(b) burden than people realise.
What looked like an idiomatic BigQuery MERGE was scanning the full target table on every batch. The fix was syntactic, not architectural — and it was the single biggest contributor to a 57% data-warehouse cost reduction across the Tata Group engagement.
Notes from contributing to Google's open-source Spanner Migration Tool (HarbourBridge). Where to start reading the codebase, where the load-bearing logic lives, and the parts that look simple but aren't.
Spanner partitions by primary-key range. A monotonically-increasing PK like a timestamp or UUID-v1 funnels all writes to one server. The fix changes everything from your sequence strategy to your tenant model.
Interleaving a child table into its parent co-locates the rows for fast joins. It also tightens coupling in ways that bite you on the next schema migration. A practitioner's decision matrix.
5K+ loans per month. Three credit bureaus. Multiple payment gateways. The thing that has to be right is the ledger. Notes on what invariants the database enforces vs what the application enforces.
Board policy as a YAML file the risk team owns. Annexure VI as a database query. Every governance recommendation rendered as a file path in a Go repository.
The RBI FREE-AI incident reporting form, expressed as a Go struct and a Postgres table. Every entry is an auto-generated artefact from the runtime — not a form an operator fills in retrospectively.
Postgres over the latest vector DB. Go stdlib over the framework du jour. Single binary over Kubernetes operator. The choices that bore reviewers and delight on-call engineers.