PlanetScale's TIN Makes Postgres Full-Text Search 25x Faster

A benchmark published on September 16th shows a performance gap in Postgres full-text search that's hard to believe: 25x throughput, 26x lower latency. Not marketing copy โ there's a table, an 85GB corpus, and a named competitor.
What happened
PlanetScale, the managed Postgres/MySQL cloud provider, just shipped TIN (Text INdex), a full-text search extension for Postgres. It's already GA across every PlanetScale and Neki database. The syntax reads like any other index:
CREATE INDEX an_index_name ON table_name USING tin(text_column_name);
SELECT * FROM table_name
WHERE text_column_name ==> 'some words';
Postgres already ships a built-in GIN index for full-text search, and the ecosystem already has extensions like ParadeDB and pg_textsearch. PlanetScale claims TIN beats all three โ and backs it up with numbers instead of adjectives.
The benchmark: not a marginal gap
PlanetScale tested on an AWS i7i.8xlarge instance, capped at 8 vCPUs and 32GB RAM per container, using an 85GB corpus of 150 million Stack Exchange questions and answers. They compared TIN v1.0.2 against ParadeDB v0.25.2, pg_textsearch v1.4.0, and the built-in Postgres GIN index (Postgres 18.6).
Index build times alone show a clear split:
| Engine | Build time | Index size | RAM required |
|---|---|---|---|
| TIN | 8m10s | 50.7 GB | 32 GB |
| ParadeDB | 19m20s | 52.1 GB | 64 GB |
| pg_textsearch | 26m49s | 41.5 GB | 128 GB |
| Postgres GIN | 2h09m04s | 28.0 GB | 64 GB |
Query performance โ the part that actually matters in production โ widens the gap further. On a mixed workload of conjunction, disjunction, and phrase queries returning the top 10 results by BM25 score, TIN hit 199 QPS with 256ms p99 latency. ParadeDB managed 7.9 QPS with a 6,765ms p99. That's 25x more queries per second, and even the slowest queries are 26x faster. Postgres GIN couldn't finish this benchmark at all โ it ran out of memory on the disjunction searches.
On conjunction and phrase queries alone, TIN is 10x faster than ParadeDB and 541x faster than GIN. Even with a concurrent client hammering 1,000 UPDATE queries per second, TIN completed 270,279 updates in a 10-minute run, versus 185,584 for ParadeDB and just 735 for pg_textsearch โ pg_textsearch's constant read traffic starved writes of the locks they needed.
Why it's fast โ skipping a translation step nobody talks about
This is the more interesting part. Most text indexes, including ParadeDB and pg_textsearch, assign sequential document IDs within each segment to keep postings lists compressible. But Postgres internally doesn't use sequential IDs โ it uses ctid, a 48-bit number that points directly to a row's physical location on disk.
The result: whenever a search matches 10 million rows, ParadeDB and pg_textsearch have to translate those 10 million sequential IDs back into real ctids through a separate mapping structure. TIN skips that entirely โ it uses ctid as the document identifier from the start. No mapping, no lookup, no middle layer.
The tradeoff is a harder compression problem. ctids are discontiguous 48-bit numbers, not sequential, so classic tricks like delta-encoding don't apply. PlanetScale's answer is a two-level bitmap that exploits a Postgres quirk: no page can hold more than 291 tuples, so a page-level bitmap stays dense enough to compress well. For high-frequency terms, they get down to roughly 1 bit per posting.
So what does this mean for developers?
If your team has been building search โ e-commerce, log search, internal docs โ on top of Postgres and quietly considering "let's just bolt on Elasticsearch or Meilisearch," these numbers are worth a second look. A 10-25x QPS gap is big enough to change the calculus on whether you need a separate search system at all. Staying inside Postgres means one less service to operate, one less sync pipeline, one less failure point.
Two caveats worth keeping in mind, though. First, this is a benchmark PlanetScale published about its own product, not an independent third party โ even though they shared the corpus, the exact queries, and a forked benchmarker, you should still reproduce it against your own workload before switching anything. Second, TIN is currently GA on PlanetScale's own infrastructure; it's unclear at the time of writing whether a standalone version exists for self-hosted Postgres, so teams not already on PlanetScale should verify availability before expecting to use it right away.
For anyone already running on PlanetScale, this is a solid reason to try CREATE INDEX ... USING tin(...) on a real table and measure it against your own workload instead of trusting the marketing numbers.
What to know
- TIN (Text INdex) is PlanetScale's new full-text search extension, GA for every PlanetScale/Neki database, shipped September 16, 2026
- Benchmarked on an 85GB Stack Exchange corpus: 10-25x faster QPS than ParadeDB, up to 541x faster than built-in Postgres GIN on some query types
- The trick: using Postgres' native
ctidas the document ID directly, skipping the sequential-ID mapping layer other engines need - Keeps solid throughput even with 1,000 concurrent UPDATE/sec โ traditionally a weak spot for text indexes
- The benchmark is self-published by PlanetScale; availability outside PlanetScale's own infrastructure is unclear at the time of writing
Content assisted by AI (Amy ๐ธ). Reviewed by the author.
Related Posts
AWS Acquires DuckLabs, the Team Behind DuckDB โ What It Means
Amazon signed a deal to acquire DuckLabs, the company behind DuckDB. MIT and the foundation stay โ but can DuckDB stay neutral for every vendor?
Rust Glancer: A Rust LSP That Runs Under 100MB of RAM
rust-analyzer can eat gigabytes of RAM. Rust Glancer flips the architecture โ index once, store to disk, idle under 100MB.
DuckDB 2.0 Preview: From Embedded Library to a Real Server
DuckDB 2.0's preview turns the embedded analytics engine into a real server, adding the VARIANT type, triggers, and a 40x faster recursive query.