Fast Search, Slow Search, Cheaper Search · Morning Gist
Friday, October 94 stories · 12 min
Fast Search, Slow Search, Cheaper Search
Three of today's four stories are about search: PlanetScale ships a fast index and a slow test double for it, and Pinterest moves vectors to SSD. The fourth is about management.
Picked from 51 new articles across 34 sources · arrow keys for other days
Today in 30 seconds
30s left
PlanetScale's TIN Postgres search index runs mixed top-10 queries at 413/sec in v1.0.6, up from 110, with the same on-disk format. story 1 ↓
TIN v1.0.6 also adds stemming. Most of the speedup comes from skipping blocks of results, a looser scoring rule and wider CPU vectors. story 1 ↓
Charity Majors argues that a happy team says little about its manager, because psychological safety has been cut off from accountability. story 2 ↓
PlanetScale's Lead takes TIN's SQL syntax but scans the whole table every query, giving CI a realistic but slow stand-in. story 3 ↓
Pinterest's compressed vectors cut index memory by over 50%. Moving a 5-billion-vector index to SSD saved 40% of CPU time. story 4 ↓
1/4PlanetScale· Patrick Reynolds· Oct 8
PlanetScale's TIN Postgres search index adds stemming and speeds up ranked queries
PlanetScale sped up ranked queries in TIN, its full-text search index for Postgres, and added stemming in 18 languages. In its own read-only benchmark, TIN now beats rival ParadeDB by 3–5x again.
Why it matters · The post shows how ranked text search is tuned inside Postgres: skipping blocks of results, a looser scoring rule, and CPU vector width. It also shows how much vendor benchmarks depend on configuration.
Know this first
Context from the editor, not the article · 32 sec
1 · Full-text indexes in Postgres
An inverted index maps each word to a "posting list" of the documents that contain it. Extensions like TIN and ParadeDB add this kind of index to Postgres so it can do search-engine-style ranked queries without a separate system such as Elasticsearch.
2 · BM25 ranking
BM25 is the standard relevance formula. It adds up a score for each query term that rises with how often the term appears in a document and with the term's rarity across the corpus (inverse document frequency). Common words add little to the score.
3 · The benchmark back-and-forth
2/4Charity Majors· Charity Majors· Oct 8
Charity Majors: a happy team doesn't mean the manager is doing well
Charity Majors argues that "psychological safety" was meant to help teams learn and perform. Over time it shrank into "nobody should feel bad." She says managers should aim at results, not at making their team happy.
Why it matters · Senior engineers who lead or mentor others keep running into the claim that kindness and high performance pull against each other. This essay goes after that claim with research and history, not slogans.
Know this first
Context from the editor, not the article · 37 sec
1 · What psychological safety means
Amy Edmondson, the researcher behind the academic term, defines it as "a shared belief held by members of a team that the team is safe for interpersonal risk-taking." That means being able to admit mistakes, ask naive questions or raise problems without being punished. Her research always paired it with high accountability.
2 · Project Aristotle and DORA
Project Aristotle was Google's study of what makes its teams effective, published in 2015. DORA (DevOps Research and Assessment) is a research program, running since 2014, that ties team practices to software delivery outcomes. Both looked at whole teams, not star individuals.
3 · The essay series
3/4PlanetScale· Patrick Reynolds· Sep 17
PlanetScale releases Lead, a slow but compatible search extension for testing
PlanetScale released Lead, a Postgres extension for CI and development that matches its fast TIN search index feature for feature. Lead has no index, so every search scans the whole table.
Why it matters · Shipping a deliberately slow reference version of a production dependency is a clean way to keep tests realistic without running the real system in CI.
Know this first
Context from the editor, not the article · 28 sec
1 · Full-text search in Postgres
Postgres has basic built-in text search, and extensions add richer engines. Fast engines build an inverted index, a map from each word to the rows that contain it, so a query reads only the rows that match instead of every row.
2 · BM25 relevance scoring
BM25 is the standard formula search engines use to rank matches. It weighs how often a term appears in a document against how rare the term is across the whole collection, and it adjusts for document length.
3 · Snapshot isolation
In Postgres, each transaction sees a consistent snapshot of the data. Its own uncommitted writes are visible to it, other transactions' uncommitted writes are not, and a rollback removes its writes.
Pinterest cuts vector search costs with compression and SSD-based indexes
Pinterest's search platform, Manas, now compresses stored vectors and serves some indexes from SSD. Index memory fell by over 50% and serving costs by 20–30%. Recall, the share of true nearest matches found, dropped by under 5%.
Why it matters · Holding the whole vector index in RAM makes cost grow in step with corpus size. This shows measured ways to break that link and what each one costs in result quality.
Know this first
Context from the editor, not the article · 37 sec
1 · Embeddings and nearest neighbors
Retrieval systems turn items and queries into embeddings, lists of a few hundred numbers. Similar items end up with nearby vectors. Finding the exact closest vectors among billions is too slow, so systems run approximate nearest neighbor (ANN) search. It trades a little recall for speed.
2 · HNSW versus cluster indexes
HNSW links vectors into a layered graph and searches by hopping between neighbors. It is fast and accurate, but each hop is a random memory access, so the whole graph must sit in RAM. IVF-style indexes instead group vectors into clusters and search only the clusters nearest the query.
PlanetScale released TIN three weeks earlier and called it the fastest Postgres text index. ParadeDB then tuned its extension and showed one case where it was faster: top-10 BM25 queries on read-only data. This post is PlanetScale's answer.
inverse document frequency
Measure of how rare a term is across the corpus; rarer terms get more weight in BM25.
Image: PlanetScale
PlanetScale has released 1 v1.0.6. TIN is the company's full-text search index for Postgres, launched three weeks earlier. The update was prompted by customer requests and by 2, a rival Postgres search extension, which had tuned its index to beat TIN on one workload: top-10 queries ranked by 3 (the standard relevance formula) over read-only data. By PlanetScale's own measurements, TIN is ahead again.
What changed
4. Words are reduced to a shared root, so run, runs and running all match each other. TIN uses the 5 stemming algorithms through the rust_stemmers library, covering 18 languages. Existing indexes must be rebuilt to use it.
Tiebreakers. Queries sorted by score and then by a column such as created_at used to score every matching document. Now they use the same 6 plan as plain ranked queries. Block-max splits each word's document list into blocks, records the best possible score in each block, and skips any block that can't beat the current 10th-best result.
Faster top-k queries (queries that return only the k best rows). The index format is unchanged, so no rebuild is needed for these.
The scoring shortcut
By default, TIN leaves out of the BM25 score any term found in more than 10% of documents. Those terms still must match, but they don't count toward ranking. BM25 gives rare terms more weight, so common terms change scores little but cost a lot of CPU. ParadeDB criticized this choice. Users can turn it off with tin.full_score(ctid) or set their own cutoff with dense_ratio.
Numbers
The benchmark uses ParadeDB's setup: 150 million Stack Exchange documents (85 GB), 1,254 queries, and an Intel i7i.8xlarge server. The table is static and freshly vacuumed, which the authors call a best case.
On the mixed workload, TIN handled 413 queries per second with 119ms 7 latency. ParadeDB 0.26.0 handled 98 QPS at 442ms. With all terms scored, TIN dropped to 180 QPS. The previous TIN release, v1.0.2, managed 110 QPS. Across workloads, PlanetScale reports 3.1–5.0x ParadeDB's throughput with default scoring, and 1.3–3.0x with full scoring. Graviton4 ARM machines were noticeably slower than Intel, which the authors attribute to Intel's wider 8 vector instructions.
Caveats
This is a vendor benchmarking a competitor, and the largest gaps rely on the approximate default scoring. PlanetScale says ParadeDB's speedups grew its index by 29% and require a rebuild. It also claims a large lead under concurrent writes, but the post doesn't measure it. The post also doesn't name most of the optimizations behind the gains.
PlanetScale has released 1 v1.0.4 and v1.0.6. TIN is the company's full-text search index for Postgres, launched three weeks earlier. The releases add three things: stemming, faster tiebreaker sorts in ranked queries, and broad speedups to top-k queries, meaning queries that return only the k best-scoring rows. Patrick Reynolds says the work was prompted by customer requests and by a competitor. 2, which makes another Postgres search extension, had tuned its index until it beat TIN on one workload: top-10 queries ranked by 3 (the standard relevance formula) over read-only data. PlanetScale's new numbers put TIN ahead again, by its own measurements.
4
Stemming reduces each word to a shared root form, both when indexing and when querying. running, runs and run all map to run, so a search for any of them matches documents containing any of them. The root doesn't have to be a real word: the stem of database is databas. Plurals and verb forms work differently in each language, so stemming is language-specific. TIN uses the rust_stemmers Rust library, which implements the algorithms from the project (a widely used collection of stemmers). That gives it 18 languages, including English, Arabic, Russian, Tamil and Turkish.
Stemming changes what gets written into the index, so existing indexes have to be rebuilt to use it. You update the extension, build a new index with CREATE INDEX CONCURRENTLY ... USING tin(col) WITH (stemmer = 'en'), then drop the old one concurrently. The CONCURRENTLY option lets Postgres build or drop an index without blocking writes to the table.
Tiebreakers and 6
A typical ranked TIN query filters with TIN's ==> match operator and sorts by tin.score(ctid) DESC LIMIT 10. ctid is Postgres's physical row address: a page number plus a slot within that page. Some users want ties broken in a fixed order, for example ORDER BY tin.score(ctid) DESC, created_at DESC, id.
The plain query used a block-max algorithm. This is a standard technique in search engines, described here from general knowledge. Each word's posting list (its list of matching documents) is split into blocks, and each block stores the highest score any document in it could reach. While collecting the top 10, the engine keeps track of the 10th-best score found so far. It skips any block whose maximum can't beat that score, so most matching documents are never scored.
In the GA (general availability, first public) release, adding a tiebreaker column turned that optimization off. TIN had to find and score every matching document. v1.0.6 uses the block-max plan for both kinds of query. The article doesn't say how heap columns such as created_at are folded in when scores tie.
Why TIN skips common words in scoring
The biggest performance lever, and the one ParadeDB had criticized, is a default setting. By default, TIN leaves out of the BM25 score any query term that appears in more than 10% of documents. Such terms still count for matching: a conjunction (match all words) still requires them, and a phrase query still checks their position. They just don't add to the score. Reynolds's reasoning is that BM25 weights each term by its rarity, so very common terms change scores very little. They are also expensive, because their posting lists are the longest.
Here is an illustrative example (not from the article). Take the query how to rebase. The words how and to probably appear in more than 10% of Stack Exchange posts. TIN would still require them to match, but would rank results by rebase alone. That saves walking two huge posting lists, at the cost of slightly different scores.
You can change this per query. tin.full_score(ctid) scores every term. tin.score(ctid, dense_ratio => F) sets a different cutoff. Reynolds compares the approach with traditional stop-word lists, which drop common words from the index entirely so they can't be searched at all. Whether the default still counts as "BM25" he calls a semantic question. The benchmarks report both modes: TIN (default) and TIN_FULL (all terms scored).
Benchmark setup
The setup matches ParadeDB's methodology:
Data: 85 GB of Stack Exchange questions and answers, 150 million documents.
Queries: 1,254 synthetic queries, each run three ways: disjunction (match any word), conjunction (match all words) and phrase (all words, in order).
Ranking: top 10 by BM25 score.
Hardware: an i7i.8xlarge EC2 instance (5th-generation Intel Xeon). The database container has 8 vCPUs, 64 GB RAM, shared_buffers of 24 GB, and CPUs pinned to cut down migration noise. The benchmarker runs on the same host.
ARM comparison: i8g instances (Graviton4).
Versions: ParadeDB 0.26.0 final, with its query-type-specific operators.
The table never changes, the index is built in one pass and freshly vacuumed. The authors call this "basically a best-case scenario". The only stress is that the index is about twice the size of the buffer cache.
Results (x86-64)
QPS is queries per second. p99 is the 99th-percentile latency. On the mixed workload the old v1.0.2 managed 110 QPS (TIN) and 36 QPS (TIN_FULL) on x86. That makes v1.0.6 about 3.8x and 5x faster. On ARM the gain is smaller, from 135 to 265 QPS. A "MB/query" column, which the article doesn't define, falls from 64 to 27 for default TIN.
PlanetScale's summary: with default scoring, TIN has 3.1–5.0x the throughput and 2.7–4.4x lower p99 than ParadeDB on x86. With full scoring the lead shrinks to 1.3–3.0x throughput. The weakest case is full-scored disjunctions, at 85 vs 65 QPS.
x86 beat ARM by a wide margin across the board, for example 842 vs 594 QPS on conjunctions. The authors suggest the reason is 8, Intel's 512-bit SIMD (single instruction, multiple data) instruction set, which has wider vector registers than Graviton4's Neoverse V2 cores. They ask that anyone publishing benchmarks name the exact instance type or CPU.
Trade-offs and open questions
PlanetScale says ParadeDB 0.26.0's speedups grew its index from 52.1 GB to 67.3 GB (+29%) and require a rebuild. TIN v1.0.6 keeps the same on-disk format, so it is a drop-in upgrade. Stemming, though, does need a rebuild.
Some points to keep in mind:
This is a vendor benchmarking a competitor. The headline multiples depend on TIN's default approximate scoring.
The read-only setup doesn't test concurrent writes. PlanetScale says TIN is "dramatically faster" there, because ctid-based document IDs make counting and segment merging cheaper than the sequential ordinal IDs that ParadeDB uses. That claim isn't measured or explained here.
The post doesn't name the specific optimizations behind the 2–4x gains, beyond block-max and SIMD. It also doesn't explain the ARM regression in p99 for some configurations.
Remember
Much of TIN's lead comes from leaving terms found in over 10% of documents out of the score; with full scoring the lead falls to 1.3–3x.
Block-max pruning now also covers tiebreaker sorts, which previously had to score every matching document.
CPU choice mattered a lot: Intel with AVX-512 clearly beat Graviton4, so benchmarks should state the exact instance type.
This is part 3 of a public exchange between Charity Majors, CTO and co-founder of Honeycomb (an observability company), and Cat, who writes on team learning and cognitive science. The series asks how team norms change as work changes. This part is about management practice, not AI.
Image: Charity Majors
Charity Majors, CTO of the observability company 1, has published the third essay in a public exchange with her collaborator Cat about how teams work. Cat had asked why people believe high performance and good team norms can't go together. Majors' answer: many leaders take "treating people well" to mean "nobody feels bad," and that version does conflict with performance.
How we got here
Majors traces the idea to 2015, when Google published 2, its two-year study of team effectiveness. It found that high-performing teams stood out on five dynamics, with 3 at the top. 4 (DevOps Research and Assessment), a research program linking practices to software delivery, had started a year earlier. Before them, tech celebrated individual heroics: firefighting, sleeping under desks, and "5" whose rudeness passed for genius. Both research efforts kept finding that delivery and impact happen at the level of the team.
The drift
Psychological safety is academically defined as a team's shared belief that interpersonal risk-taking is safe, and researchers always paired it with accountability. In popular use it slid toward "I should never have to feel bad at work." Majors has heard people say layoffs, missed promotions, after-hours Slack and constructive feedback damaged their psychological safety. Her correction: it matters because it enables learning, which drives performance. She adds that the effect is strongest in uncertain, interdependent work and weak in routine work.
Happiness isn't the metric
A boss once told her, "If your team is happy, you're doing a good job." She calls that typical of the 6 (zero interest-rate policy) era, when money was cheap and headcount seemed unlimited. Her test: six months of paid leave and a job tasting ice cream would make people happy, briefly. Aristotle separated 7, the satisfaction of a flourishing life, from shallow pleasure, and research by Gilbert and Kahneman shows people predict their own happiness badly. Feelings deserve respect, she argues, but they aren't an outcome to manage toward. Saying no and challenging people is part of the job.
Learning hurts, and should be measured
Learning is humbling. Admitting ignorance in front of peers builds trust because it is vulnerable. Yet a meeting labeled "learning" can be the best hour of the month or a waste, and the calendar invite won't tell you which. Majors advises treating learning like an investment: form a thesis, test it, measure it. She doesn't say what to measure.
Systems, not faces
People credit the manager who gave them a raise, not the business that funded it. Majors argues we give individuals too much credit and blame and let systems off the hook. She closes by asking Cat how she measures fairness.
Charity Majors, CTO and co-founder of the observability company 1, has published the third essay in a back-and-forth with her collaborator Cat about how engineering teams work. Cat's last piece closed with a question: "What gets us so stuck on believing we can't have both high performance and good norms?" She also noted that it is hard to get organizations to treat team learning as "the hard cognitive science of problem-solving instead of soft, squishy feelings."
Majors thinks these problems share a root. If leaders take "treating people well" to mean "nobody feels bad," they will assume it costs performance. If people link learning with pleasant feelings rather than discomfort, they probably aren't learning much. And because humans tend to see people where there are really systems, we look for fairness in the wrong places.
Before 2015: the brilliant jerk
Majors begins with history. Psychological safety came into tech vocabulary in 2015, when Google published 2, its two-year study of team effectiveness. The study found five dynamics that set high-performing teams apart:
3
dependability
structure and clarity
meaning
impact
A year before that, 4 (DevOps Research and Assessment) had started measuring how team practices relate to software delivery outcomes.
Majors says the idea of excellence before this research centered on the individual. Managers praised people for heroic firefighting and for sleeping under their desks. "Brilliant jerks" (talented but abusive engineers) were tolerated and even cultivated, because the culture tied genius to antisocial behavior. Her example is the 5, the "Bastard Operator From Hell," a long-running ops-humor character who deletes users' files for fun. Quieter high performers, "nearly all women," were told to throw their weight around more.
DORA and Aristotle started from first principles, asking what leads to the best outcomes. Their answer, which Majors says has grown stronger with each report, is that individual skill matters but delivery and impact happen at the level of the team.
How the concept drifted
The academic definition of psychological safety is a team's shared belief that interpersonal risk-taking is safe. Majors stresses that the research was always about excellence, and that researchers insisted it be paired with accountability. Most of that nuance was lost as the idea spread. Its popular meaning moved toward "I should feel safe at work" and then "I should never have to feel bad at work."
Her examples of people saying their psychological safety had been damaged: hearing bad news, layoffs, a promotion that didn't come, reorgs, a manager answering Slack after 6 pm, and constructive feedback on their work.
Her correction is about cause and effect. Psychological safety matters because it enables learning, and learning leads to performance. Feeling safe is a means, not the goal. She adds a limit the pop version leaves out. The effect is strongest in work that is uncertain, interdependent or changing, where people have to surface problems and adapt all the time. In routine, stable work it matters much less.
"If your team is happy, you're doing a good job"
When Majors became a manager for the second time, she asked her boss how he would know whether she was doing well. He answered: "If your team is happy, you're doing a good job." She calls this typical of the 6 era (zero interest-rate policy, the cheap-money years when growth and headcount seemed unlimited).
Her generation of managers was reacting to the two kinds they grew up under: the 7 (individual contributor) who didn't want to manage, and the command-and-control boss who handed out tasks. So they became coaches and sponsors, talked about "servant leadership," and said "being a manager is all about people." Majors counts this as progress. She also says that in practice it often watered down into "please be nice."
She now rejects the premise. Management is about business success first, and then, ideally, good outcomes for everyone involved. She quotes her own earlier ranking: the most effective leaders are kind people who are skilled operators. Next come unkind people who are skilled operators. Everyone else comes after that.
The ice-cream test
Her argument against happiness as the metric is a thought experiment. If happiness were the goal, she could give everyone six months off, triple their salaries, and make their job taste-testing ice cream. Would that work?
She brings in Aristotle, the philosopher the project was named after. He separated 8, the deep satisfaction of a flourishing life built through action and virtue, from hedonic pleasure, which he dismissed as "fit for cattle." She points to modern research by Daniel Gilbert and Daniel Kahneman showing that people are bad at predicting what will make them happy. What we expect to want is rarely what we value looking back.
The line she draws: people's feelings deserve acknowledgment and respect, but they are not "a business outcome we should manage to." A leader who can't stand disappointing their reports won't be effective. Saying no and pushing people is part of the job, and how people react is up to them.
Learning is uncomfortable, and that builds trust
Learning means introspection, which is humbling, and stretching your limits, which is uncomfortable. Admitting in front of peers that you don't know something is vulnerable. That, Majors argues, is why it builds trust. She cites Cat's observation that even hostile teams soften once they start asking "what did we learn together?"
She also warns against learning theater. Pulling ten or twenty people into a discussion might produce the best hour of the month, or it might start endless Slack arguments. You can't tell from the calendar invite, and often you can't tell afterward either. So some leaders underinvest out of skepticism and others overinvest and get nothing back. Her advice is to treat learning like any other investment: form a thesis, test it, invest, and measure whether you were right. Expect slow returns. The essay does not say what to measure.
People get credit for what structures do
Her last point is about attribution. People see intent and faces everywhere, "faces onto grilled cheese sandwiches." So we credit the manager who gave us a raise "because we deserved it," not the leaders who ran the business well enough to fund raises. Majors thinks expecting managers to both do the job and make us feel good is an impossibly high bar. Outcomes come from the work of hundreds or thousands of people, yet we "give individuals too much credit and too much blame, and let the system off the hook."
The essay ends without resolving this. It hands Cat a question: when you measure fairness, do you look at people or at systems, and what exactly do you look at? Readers wanting concrete metrics for team health or learning won't find them here. Majors leaves that for later in the exchange.
Remember
Psychological safety is a means to learning and performance, and researchers always paired it with accountability.
Its effect on performance is strongest in uncertain, interdependent work and weak in routine, stable work.
We credit or blame individual managers for outcomes that are often produced by systems and business results.
PlanetScale, a managed database company, announced TIN, a fast full-text search extension for Postgres. The next day it released Lead, a companion extension with the same features that is deliberately slow. Customers had asked how to build applications on TIN if they couldn't run it in 1 (continuous integration, the automated tests run on every change). The post doesn't say why TIN can't run there. Lead is meant to fill that gap.
Same interface, no index
Lead accepts the same SQL statements and the same 2 queries (TIN's search query language). It tokenizes text the same way, so a word in TIN is a word in Lead. Writes work, including CREATE INDEX, INSERT, UPDATE and DELETE. Lead is transactional with correct 3: rows you insert in a transaction show up in that transaction's searches, other transactions can't see them, and a ROLLBACK removes them. Data survives a Postgres restart. 4 relevance scoring works, including tin.score and tin.max_score, and so does hit highlighting in both HTML and ANSI terminal output.
The difference is that every Lead search is a 5. "We've left out all the parts that make TIN fast, but kept the rest," the post says. The article doesn't describe Lead's internals. My reading is that scanning through ordinary Postgres table access lets the database's own row visibility rules handle transactions and rollbacks. A real search index would have to get those right by itself.
The numbers
An 8.0 GB Wikipedia corpus: TIN handles 10,260 queries per second with a 2 ms 6. Lead takes about four minutes per query.
War and Peace, 3.4 MB or about half a million words: Lead answers in about 170 ms. The post calls this unofficial.
By my arithmetic, both work out to tens of megabytes per second, which fits a linear scan. PlanetScale's advice is to keep CI tables under a few megabytes.
Trade-offs
The recommended split is TIN in production and Lead for tests, CI, development and staging. That catches mistakes in query meaning without mocking, but it can't catch performance problems. It also relies on PlanetScale keeping the two implementations in sync. The company promises to port new tokenizers to Lead and asks users to report differences. Staging environments that hold production-sized data will hit Lead's scan costs. The post doesn't say how parity is tested or what license Lead uses. Lead can be downloaded now.
PlanetScale, a company that hosts managed MySQL and Postgres databases, announced TIN, a full-text search index extension for Postgres. A day later it released Lead, a second extension that implements the same features with none of the speed. According to Patrick Reynolds's announcement, customers asked how they could build applications on TIN if they couldn't run it in 1 (continuous integration, the automated test runs on each change). Lead is the answer. The post doesn't explain why TIN can't run in CI. It only says that it can't.
The problem: testing against a dependency you can't run
This is a common situation. Production depends on a component, such as a managed service or a proprietary engine, that you can't start inside a test container. The usual workarounds are weak. You can mock the search calls, and then your tests check nothing about query semantics. You can skip search tests entirely. Or you can point tests at a shared remote instance, which brings flakiness, cost and shared state. A search extension is a particularly bad candidate for mocking, because its behaviour is complex. Tokenization decides what counts as a word, query syntax can be intricate, relevance scores determine result order, and results must respect transaction visibility.
PlanetScale's answer is a reference implementation. Lead is a second real implementation of the same interface that gives up performance to be simple and portable.
What Lead keeps
The post lists the parity points:
Same interface. The same SQL statements and the same 2 queries (TINQL is TIN's search query language) run unchanged.
Same tokenizing. Whatever TIN treats as a word, Lead does too. New tokenizers added to TIN will also come to Lead.
Writes.CREATE INDEX, INSERT, UPDATE and DELETE all work.
ACID with correct 3 (ACID: atomic, consistent, isolated, durable). Rows inserted in a transaction are visible to searches in that transaction and invisible to concurrent ones. A ROLLBACK makes them disappear.
Durability. The index survives a Postgres restart, so tests that restart the database still work.
4 scoring, including the tin.score and tin.max_score functions.
Hit highlighting, which marks matched terms in results, in both HTML and ANSI (terminal colour codes).
The post says search results are correct "even for complicated SQL and TINQL queries."
What it drops, and why that's the design
"We've left out all the parts that make TIN fast, but kept the rest," the post says. Every Lead search is a 5.
The post doesn't describe Lead's internals. A plausible reading, which is my inference and not the article's, is that the scan is what makes the correctness promises cheap. If Lead reads rows through Postgres's normal table access, then Postgres's own 6 machinery (multi-version concurrency control, which decides which row versions each transaction can see) handles visibility. Snapshot isolation, rollback and crash durability would then come almost for free. A real inverted index has to get every one of those right on its own. BM25 needs statistics across the whole collection, such as how many documents contain a term. A scan can compute these directly at query time. An index has to maintain them as rows change.
The numbers
The post gives a few measurements:
Workload
TIN
Lead
8.0 GB Wikipedia corpus
10,260 queries/sec, 7 2 ms
The War and Peace figure is labelled "unofficial benchmarking." My own rough arithmetic from these figures: 3.4 MB in 170 ms is about 20 MB/s, and 8 GB in 240 s is about 33 MB/s. Both suggest throughput that stays roughly linear in data size, which is what a scan would produce. The guidance follows from this: keep CI tables under a few megabytes and query times stay in the low hundreds of milliseconds.
Trade-offs
The split the post recommends is TIN for production and Lead for tests, CI, development and staging. A few consequences are worth thinking through, though the article doesn't discuss them:
Performance bugs go uncaught. A query that is slow on TIN, or a plan that behaves differently at scale, won't show up against a scanner that is uniformly slow. Load testing still needs TIN.
Parity is a promise you have to keep. Two implementations can drift apart. PlanetScale commits to porting tokenizers and asks users to file tickets or post on Discord when Lead differs from TIN. How parity is verified, for example by running a shared conformance suite against both, isn't described.
Staging on Lead only works if staging data stays small. Many teams' staging environments hold production-sized copies, and there Lead's scan costs would hurt.
The pattern is familiar from local emulators for cloud services, where a functional stand-in lets you test without the production engine. Lead's name is a joke along these lines: tin and lead are both metals, and lead is the heavy one.
What's open
The post leaves several questions unanswered: why TIN itself can't run in CI, what license Lead uses, how differences between the two will be detected, and whether Lead's results and scores match TIN's exactly or only closely. Lead can be downloaded from a public repository now.
Remember
Lead matches TIN's SQL, query language, tokenizer, BM25 scoring and transaction semantics, so tests exercise real search behaviour.
On 8 GB, TIN serves 10,260 queries per second; Lead takes about 4 minutes per query. Lead suits only tables of a few megabytes.
A slow reference implementation catches mistakes in query meaning but not performance problems, and parity between the two has to be maintained.
The standard retrieval model uses two networks, or "towers". One encodes the query and the other encodes the candidate, each as a single vector. Relevance is the dot product of the two vectors. It is cheap to compute but can only express limited kinds of similarity.
How scalar and product quantization each turn a float vector into compact integer codes.1 / 4
Pinterest has described three changes to 1, its in-house distributed search platform. Manas runs on more than 80 clusters, holds billions of embeddings, and serves Home Feed, Search, Ads and other surfaces.
The problem
The corpus is heading toward tens of billions of vectors. The default 2 index, 3, is a graph that search walks neighbor by neighbor. It needs the whole index in RAM, so memory cost grows linearly with corpus size.
Quantization
The team compresses vectors in two ways:
4 maps each float dimension to a small integer.
5 splits the vector into chunks and stores, for each chunk, only the ID of its nearest K-Means cluster center.
On 100 million vectors, PQ shrank indexes by 74–93% but 6 fell to 70–80%. SQ shrank them by 59–75% and kept recall above 90%. Pinterest ran A/B tests to pick a method for each use case. Index memory fell by over 50% and serving costs by 20–30%.
A variant called Linear Scaling SQ compresses with a scale factor only, so stored vectors need no decoding before distances are computed. Combined with 7 instructions that process many 8-bit integers at once, it cut per-query compute by 10–15%.
Serving from SSD
NVMe SSDs cost about a tenth as much per gigabyte as RAM, but each read is roughly a thousand times slower. Queries must therefore make few random reads. The team compared two disk-based algorithms:
8 stores a graph index on disk.
9 keeps cluster centroids in memory and stores each cluster's vectors on disk as a "10". A query reads only the lists for its nearest clusters.
Pinterest's change was to PQ-compress the on-disk vectors while keeping full-precision centroids. That version ran 4.5x faster than plain SPANN and delivered over 3x DiskANN's queries per second at a third of the latency, with about a 5% recall drop.
Balanced clustering keeps posting lists similar in length, which keeps tail latency low. On a 5-billion-vector recommendation index, SPANN used over 40% less CPU than HNSW, with recall under 5% lower. Early tests showed 10x less memory.
Multiple vectors per item
Late-interaction models such as 11 give each query and document one vector per token. They score by matching each query vector to its best document vector and summing the matches ("Sum of MaxSim"). Manas added a query type that runs several ANN searches at once. A pilot is under way.
Caveats
All figures are relative; there are no absolute or p99 latencies. The article doesn't explain how SPANN keeps Manas's seconds-level freshness. It names SPFresh, a design for updating SPANN indexes in place, as future work.
Pinterest's infrastructure team has published an update on 1, the company's in-house distributed search platform. The update covers three changes to how Manas serves embedding retrieval:
compressing vectors (quantization)
serving indexes from SSD instead of RAM
supporting queries where each item has several vectors
Manas runs on more than 80 clusters and holds billions of embeddings. It backs Home Feed, Search, Related Pins, Ads and Notifications. It supports several 2 algorithms, hybrid queries that mix keyword tokens with embeddings, and real-time updates that make new content searchable within seconds.
The problem
The corpus is heading toward tens of billions of embeddings. The default index, 3 (Hierarchical Navigable Small World, a graph where search hops from neighbor to neighbor), needs the whole index in RAM to keep latency low. That means memory cost grows linearly with corpus size. The team names a second limit on the modeling side. Two-tower retrieval reduces every candidate to one vector and scores it with one dot product, which leaves little room for context-dependent similarity.
Quantization: smaller vectors
Both methods turn float vectors into integers.
4 maps each dimension's float value to a small integer on a uniform scale.
5 splits the vector into subvectors. It runs K-Means clustering separately within each subspace, then stores only the ID of each subvector's nearest cluster center (centroid).
An illustrative example, not from the article: a 256-dimension float32 vector takes 1,024 bytes. With 8-bit SQ it takes 256 bytes. With PQ using 32 subvectors and 256 centroids each, every subvector becomes a one-byte ID, so the vector takes 32 bytes. PQ compresses much harder, but it keeps only the nearest centroid, so it loses more detail.
Pinterest benchmarked both on 100 million GraphSage embeddings. GraphSage is a graph neural network method that produces vectors for nodes in a graph.
Quantizer
HNSW index size
IVF index size
Recall
PQ
−74%
−93%
70–80%
SQ
−59%
−75%
consistently >90%
IVF (inverted file) is an index that groups vectors into clusters. HNSW shrinks less than IVF, probably because the graph's neighbor links stay uncompressed. That is our inference; the article doesn't say. Because the trade-off was clear, the team ran an online A/B test for each use case to pick a quantizer, requiring negligible impact on engagement. Across major use cases, index memory fell by more than 50% and serving costs by 20–30%.
Compression adds compute: normally SQ codes are decoded back to floats before distances are computed. Pinterest built "Linear Scaling SQ", which quantizes using a scale factor only. The article stops there. Our reading is that a scale-only mapping preserves dot products up to a constant, so distances can be computed directly on 8-bit integers. 6 instructions (single instruction, multiple data, which process many small integers in one CPU instruction) then do the work. Per-query compute fell 10–15%.
SSD serving: index out of RAM
NVMe SSDs cost roughly an order of magnitude less per gigabyte than RAM. But an access takes microseconds rather than nanoseconds, so a query that makes many random reads gets slow. To work from SSD, an algorithm has to bound the reads each query makes. Pinterest compared two such algorithms on a 100M-vector corpus from a Search use case:
7 is a graph index stored on disk.
8 is cluster-based. It keeps cluster centroids in memory and stores each cluster's member vectors on disk as a "9". A query finds its nearest centroids in RAM, then reads only those posting lists from disk.
Pinterest made one change to SPANN: it applied PQ to the vectors stored on disk but kept the in-memory centroids at full precision. That makes posting lists smaller and faster to read and scan. Precise centroids still route each query to the right clusters. Results:
SPANN+PQ ran 4.5x faster than plain SPANN.
It delivered more than 3x the queries per second (QPS) of DiskANN at one-third the latency.
Recall dropped about 5%.
In Manas, cluster centroids are chosen with SPANN's hierarchical balanced clustering, which keeps clusters close in size. Equal-length posting lists mean no query reads an unusually large one, which keeps tail latency down. The centroids are themselves indexed with HNSW, which suits a small set of vectors held in memory.
On a Pin recommendation use case with more than 5 billion embeddings, SPANN used over 40% less CPU time on production queries than HNSW, with under a 5% 10 drop. Early experiments showed memory down 10x. The next step is to roll SPANN out to all major use cases.
Multi-embedding retrieval
The third change targets the model. Late-interaction models such as 11 represent a query and a document each as a list of vectors, roughly one per token. They score with "Sum of MaxSim": for each query vector, find its highest similarity to any of the document's vectors, then add up those maximums. An illustrative example: the query "red velvet sofa" has three vectors. "Red" best matches a color token in the Pin and "sofa" best matches "couch". Each word gets its own best match instead of being blended into one average vector.
To support this, Manas gained a new query type. The query parser now handles multiple query embeddings, and Manas runs several ANN searches at once for a single query. A pilot with one product team is in progress. The article doesn't explain how results from the parallel searches are merged and rescored. It also doesn't say how much extra storage per-token document vectors need, which is a known cost of ColBERT-style systems.
What's open
The article reports relative numbers only. It gives no absolute latencies, no p99 figures, no recall@k definition, and no details of how DiskANN was tuned for the comparison. It doesn't say whether "5% recall drop" means percentage points.
Freshness is a gap. Manas promises updates within seconds, yet SPANN's posting lists are built offline. The roadmap names SPFresh, a follow-up design for updating SPANN indexes in place, but doesn't say how updates work today. The plan also includes first-class ColBERT-style retrieval and GPU-based systems named SilverTorch and TIGER, which the article doesn't describe.
Remember
Choose quantizers per use case with online A/B tests; offline benchmarks showed a large recall gap between PQ and SQ.
Cluster-based SSD indexes work when clusters are balanced, keeping per-query disk reads bounded and predictable.
Compress the large on-disk data but keep the small in-memory routing data at full precision.