12.5 million Wikipedia passages for about $4.60 a month
Benchmarks are easy to make flattering. I wanted to see whether polign_db held up against something closer to production traffic: a corpus I had not curated, queries I had not chosen, and a public endpoint that anyone could point at and hammer.
The plan was to load a slice of Wikipedia. The slice kept looking like a favor I was doing myself, so I imported all of it instead: every English article, 12.5 million passages, embedded and indexed onto one small instance and an S3 bucket. Then I put it at demo.polign.com and left it running.
The results are satisfactory. The whole corpus serves out of object storage, the search server idles at 37 MiB of RAM, warm queries come back in 25 to 50 ms, and nothing along the way needed a bigger box. The number I did not expect was the bill: about $12 a month for the whole live site, everything included.
Then I looked at what that $12 was buying, and most of it was not the database. It was the demo: an embedding model, a web app, and a public HTTPS endpoint, all sharing the box. The part that is actually polign_db serving 12.5 million passages is about $4.60 a month. Both numbers are itemized below. The vendor comparison further down uses the $4.60 one, because none of the vendors embed your text or host your app either.
demo.polign.com is
the result: live semantic, keyword, and hybrid search over 12,519,135 passages from 5.36
million articles, embedded with bge-small-en-v1.5. Below I itemize what it
costs to run, then price the same workload on five managed vector databases using their
published pricing.
The workload
- 12,519,135 passages from the
wikimedia/wikipedia 20231101.endump. - 384-dimensional vectors from
bge-small-en-v1.5, int8-quantized ONNX, running on the same box (8-10 ms per query embedding). - An IVF index with product-quantized codes: 96 bytes per vector instead of 1,536.
- ~56 GB in S3, the system of record: full vectors, compressed index, passage text, and the keyword index. Logically that's ~19 GB of raw fp32 vectors plus ~9 GB of text and metadata.
- Serving from a single t4g.small (2 vCPU, 2 GB RAM). The search server idles at 37 MiB RSS; nothing is pinned in memory.
The itemized bill, with the Wikipedia demo built in
This is the whole live site, not just the database: polign_db plus the embedding model, the search UI, and the public HTTPS endpoint that together make demo.polign.com a thing you can click on. Everything on this list shares one box.
| Item | What it does | Monthly |
|---|---|---|
| EC2 t4g.small, spot, us-east-1 | Runs the search server, the embedding model, the demo app, and TLS. ~$0.007/hr at the August 2026 spot price ($12.26/mo on-demand) | $5.11 |
| Public IPv4 address | $0.005/hour | $3.65 |
| EBS, 20 GB gp3 | Boot volume plus a 6 GB disk cache for hot index regions | $1.60 |
| S3 standard, 56 GB | The entire collection: vectors, index, text | $1.29 |
| S3 requests + egress | Cold searches cost ~$3.20 per million; demo traffic rounds to cents | < $0.50 |
| Total | ≈ $12.15 |
Spot is safe here because the node is disposable: the S3 bucket is the system of record and the node runs read-only, so a spot reclaim loses nothing. A persistent spot request restarts it when capacity returns. One-time build cost: embedding and indexing all 12.5M passages took ~7 hours on a c7g.12xlarge: about $12 of EC2, plus under $1 of S3 PUTs. The build box was terminated afterward; it is not part of the monthly bill.
How much of that is the database?
Not much of it. The demo box is doing four jobs, and only one of them is polign_db.
Here is ps on the live host, sorted by resident memory:
| Process | What it is | RSS, idle |
|---|---|---|
python | ONNX sidecar holding bge-small-en-v1.5, embeds each query | 160 MiB |
caddy | Public HTTPS endpoint, Let's Encrypt certificates | 39 MiB |
polign-server | The database | 37 MiB |
polign-demo | The search UI you type into | 30 MiB |
The embedder is why the box is a t4g.small. polign-server peaks around 420 MiB while answering queries and idles at 37 MiB, which fits a 1 GB t4g.micro with room to spare; the sidecar, the app, and Caddy on top of that do not. The public IPv4 address is there for the same reason: the demo is a public website. A polign_db node serving your own application sits in a private subnet, reaches S3 through a gateway VPC endpoint (which AWS does not charge for), and needs no public address at all.
So the same 12.5M-passage collection, served by polign_db alone, prices out like this:
| Item | demo.polign.com | polign_db alone |
|---|---|---|
| EC2, spot, us-east-1 | t4g.small, 2 GB $5.11 | t4g.micro, 1 GB $2.34 at $0.0032/hr |
| Public IPv4 address | $3.65 | $0 private subnet, S3 gateway endpoint |
| EBS gp3 | 20 GB $1.60 | 12 GB $0.96, OS plus the 6 GB disk cache |
| S3 standard, 55.8 GB | $1.29 | $1.29 |
| S3 requests + egress | < $0.50 | < $0.50 |
| Total | ≈ $12.15 | ≈ $4.60 |
Spot prices checked in us-east-1 in August 2026. On on-demand pricing the polign_db column is ≈$8.40 ($6.13 for the t4g.micro). The disk-cache size is a tuning knob, not a requirement: 6 GB is what this demo gives it, and the cache is currently full at 6.1 GB. Everything the database actually needs to be durable is the $1.29 of S3.
$4.60 is the number the rest of this post compares. It is the fair one, because no vendor below embeds your text or hosts your app either: on any of them you would still be paying for that sidecar and that web app somewhere. The demo just happens to run all of it on one box.
The same workload at published prices
Below is what this dataset (12.5M records, 384-dim vectors plus the passage text) prices out to on each vendor's public pricing page as published in August 2026, split into the three components every bill reduces to: storage, fixed compute, and per-search operations. Where a vendor bills by logical data size we use ~28 GB (vectors + text); where it bills by dimensions stored, 4.81 billion. There are two total columns, because the fair comparison depends on what the data is doing: at rest (the corpus is parked and durable, nobody is searching) and serving one million searches in a month. A million is the useful unit here: it is the scale at which the metered columns stop rounding to zero and the pricing models separate.
| Service | Storage /mo | Fixed compute /mo | Per 1M searches | Floor /mo | At rest /mo | At 1M searches /mo |
|---|---|---|---|---|---|---|
| Pinecone (Standard, serverless) | ~$9.30 $0.33/GB × 28 GB |
$0 serverless |
~$448 1 RU per GB of namespace per query: 28 RU × $16/M |
$50 | $50 floor |
~$457 $9.30 storage + 28M read units |
| Weaviate Cloud (Flex) | ~$22.40 bundled 4.81B dims × $0.00465/M, storage and serving priced together |
$0 metered bounded by cluster throughput |
$45 | $45 floor |
$45 flat; no per-search meter |
|
| Qdrant Cloud (dedicated) | included cluster disk |
~$120-200 ~8 GB-RAM cluster, calculator-priced |
$0 metered bounded by cluster size |
n/a | ~$120-200 cluster must stay up |
~$120-200 flat; no per-search meter |
| Zilliz Cloud (serverless) | ~$1.10 $0.04/GB × 28 GB |
$0 serverless |
~$152 ~38 vCU/query at this scale × $4/M vCU |
none | ~$1.10 storage only |
~$153 $1.10 storage + ~38M vCUs |
| turbopuffer (Launch) | ~$0.60 $0.02/GB × 28 GB |
$0 serverless |
~$1 $1/PB scanned, 1.28 GB min per query |
$16 | $16 floor |
$16 usage ~$1.60, floor still applies |
| polign_db (one serving node in your AWS account) | $1.29 55.8 GB × $0.023 S3 |
$3.30 spot t4g.micro $2.34 + 12 GB EBS $0.96, no public IPv4 |
~$3.20 cold, ~$0 warm S3 GETs at 8 regions probed; disk-cache hits are free |
none | $1.29 bucket only; nodes scale to zero |
~$7.80 $4.60 node + bucket, plus ~$3.20 of S3 GETs, worst case |
The polign_db row is the database on its own, not the demo box: no embedding sidecar, no web app, no public IPv4, which is what makes it comparable to the vendor rows. Every column here, ours included, excludes embedding; you would still need to embed 12.5M passages and run your app somewhere on any of these. "At rest" means the corpus is stored and durable with zero searches. For polign_db that is the S3 bucket alone: nodes are stateless and scale to zero, so the $3.30 of compute is the price of keeping a node answering 24/7, not of the database. One honest asymmetry: Zilliz's parked data is still instantly queryable; a parked polign_db collection needs a node started first (seconds to boot, then cold reads warm the cache). Per-search math, from vendor docs: Pinecone charges 1 read unit per GB of namespace per query regardless of top-k, so a 28 GB namespace costs 28 RUs every query. Zilliz's own reference table puts 1M reads on 10M 768-dim vectors at 55M vCUs; scaled to our 12.5M × 384-dim collection that's ~38 vCUs per query. turbopuffer bills scanned bytes at $1/PB with a 1.28 GB per-query minimum. Pinecone also sells a $20/mo flat Builder plan; its included usage isn't published and requests beyond it are blocked rather than billed, so we priced the usage-based Standard plan. Zilliz's 5 GB free tier is too small for this dataset. One-time loading costs at published write prices: ~$112 on Pinecone (28M write units) and ~$56 on turbopuffer ($2/GB), against our ~$12 build, which included the embedding compute.
What a million searches costs
Storage and fixed compute are flat. The per-search column is the one that moves, and the vendors are two orders of magnitude apart on it: ~$448 per million searches on Pinecone, ~$152 on Zilliz, ~$1 on turbopuffer, and ~$3.20 on our stack. Ours is a worst case that assumes every query reads cold from S3; repeated queries hit the disk cache and cost nothing. Weaviate and Qdrant have no per-search meter at all, because you are renting a cluster: their price is flat until the cluster runs out of headroom, and then it steps up.
The reason Pinecone and Zilliz land so high is that both meter a share of the data scanned, so the price of a search rises with the size of your corpus. Pinecone charges one read unit per GB of namespace on every query, so our 28 GB corpus costs 28 units per search no matter how few results come back. Zilliz's vCUs per query climb the same way, from 55 per query on 10M 768-dim vectors to 290 on 100M 1536-dim in their own reference table. Double your corpus and every future search costs about twice as much. On our side the corpus size is not in the formula: a search reads the index regions it probes, which is a tuning knob (nprobe), not a function of how much data sits in the bucket.
That gives a crossover rather than a winner. Zilliz is cheaper than a polign_db node below roughly 23,000 searches a month, because $3.30 of always-on node beats their meter only once the meter has something to count. turbopuffer's $16 floor beats us until about 3.5M searches a month. Past those points the flat shape wins and keeps winning: at 10M searches a month Pinecone is ~$4,500 and Zilliz ~$1,500, while our bill is ~$37. To be fair about it, 10M searches a month is about 4 queries per second, and a t4g.micro has not been asked to sustain that; stepping up to the t4g.small the demo runs on adds about $3.
What these numbers don't say
This is not a claim that managed services are overpriced. Their fees buy real things ours doesn't include: replication, SLAs, support, and an index that is always warm. Our warm queries return in 25-50 ms, but the first touch of a cold region takes 0.4-2 s. An always-in-RAM service will beat that, and if your workload needs uniformly fast queries at high QPS, a RAM-resident index is the right tool and costs what it costs.
Our EC2 line uses the spot price, which is fair to flag: spot capacity can be reclaimed, which briefly interrupts serving until the persistent request relaunches the node. An always-on service doesn't have that blip. On on-demand pricing a polign_db node is ≈$8.40/month and the demo stack is ≈$19/month, both still below three of the five floors.
It's also worth being plain that the serverless entries are genuinely cheap at low volume. Below the crossover, Zilliz serverless runs this corpus for less than we pay AWS for a node, and turbopuffer's ~$1 per million searches is the best per-search price in the table by a wide margin. Comparing their storage-only idle cost against our storage-plus-node total wouldn't be fair in either direction, which is why the table splits at rest from serving. They're cheap for the same reason we are: object storage is the right substrate for corpora that are mostly cold. The difference isn't the substrate. It's whose account the data sits in, and what the per-search line does as both traffic and corpus grow.
Is this serverless?
The at-rest column raises a fair question: if a parked collection is just a bucket, isn't polign_db serverless too? Half of it is. Economically, yes: the bucket is the database, it bills at S3 rates with no floor, and nothing ticks while nobody searches. That is the same scale-to-zero property the serverless vendors get from building on object storage, and it's why the at-rest row converges to a few dollars for all three object-storage architectures.
Operationally, no. The difference is where the meter comes from. A serverless vendor keeps a multi-tenant query fleet warm around the clock, so your parked data is instantly answerable; the per-operation price is how their always-on fixed cost becomes your marginal cost, with margin. polign_db has no pooled fleet standing behind your bucket: a parked collection answers nothing until you start a node, and the query compute is yours to bring. Call it serverless at rest, server-ful when serving: you're not renting a slice of someone's warm fleet, you're deciding when a fleet exists at all. The demo chose the server-ful mode: $3.30 a month buys a node that answers 24/7 with no per-search markup, and the other $7 of its bill buys the embedder and the public address that make it a website. If it got one query a day, the rational shape would flip: park the bucket at $1.29 and start a node on demand. And because a node boots in seconds and holds nothing durable, a function-shaped node (start, answer, vanish) is a natural extension of the same read path.
The shape of the bill is the point
What we'd point at in our column isn't the total. It's the structure. The compute is one small box you could replace in five minutes, because the S3 bucket is the system of record. That is also what makes spot pricing safe, and how the node earns its ~60% compute discount. Storage grows at S3 rates ($0.023/GB), not at vector-database rates. Searches that never happen cost nothing: there is no minimum, no floor, and a collection that sleeps bills $0. And the entire thing lives in your AWS account (the corpus, the index, the bill) with no per-query markup between you and your data.
At this scale the floors are the story: four of the five managed options charge more as a minimum than a polign_db node costs to run, and all four of them charge more than the entire demo box, embedder and public endpoint included. At larger scale the storage multiple becomes the story instead: the benchmarks page has the measured numbers, and the comparison page covers what a terabyte costs across architectures.
See it yourself
The demo is live at demo.polign.com. Every query you run there is served from the $12 stack described above. To run the same thing on your own bucket, start with the getting started guide.