NEW: Instant namespace branching

Building the database for trillion-scale AI search

April 12, 2026AI Council Conference

Transcript

Nikhil [0:00]:
I'm Nikhil, CTO at turbopuffer, as I just mentioned, and we are building the database for trillion-scale AI search. And what do I mean by that? I mean that turbopuffer can search over trillions of documents, whatever documents mean to you, whether it's issues or comments or Slack messages or photos or satellite images, anything that an LLM understands, that's a document that you can ingest into turbopuffer and then search over, even if you've got a trillion of them. Now in this talk, I'm going to assume a little bit of familiarity with vector search and with old school keyword search, full-text search. Can I get a quick show of hands just so I know how many people I might be leaving behind by assuming that? How many of you are familiar with vector search? Excellent. I love that. It is AI Council after all. How about full-text search? Perfect. We're just going to blast right into it.

So where do you start when you set out to build a system that does trillion-scale search? And the answer is you start at the beginning. You start with a very simple system. And this isn't something that turbopuffer discovered. This has been a well-known phenomenon in systems building for over 50 years when John Gall, who studied systems of all sorts, everything from healthcare systems to educational systems to bureaucracies to software systems, he noticed that every complex system he observed that worked originated from a simple system that worked. But if you try to design a complex system from scratch, start with that complexity, it invariably fails. And that's at the heart of the way that we build everything at turbopuffer, from the very first version of turbopuffer to every feature that we add on to the system. It has to be simple.

Now, there's one overriding concern that comes before simplicity, and that's correctness. If you simplify your system so much that it ceases to be correct, you no longer have a useful system. So correctness always has to come first. But one interesting side effect of this focus on simplicity is you can actually trade off performance. And this is maybe surprising. But at turbopuffer, we're very happy to ship something that is slow but simple instead of something that's fast but complicated. And the reason for this is time and time again we discover that our intuition for what's going to matter in production is just completely wrong. Either the bottleneck isn't where our understanding of computer architecture said it would be, or users just aren't using the feature in the way that we would expect. So we always prefer to ship the simple thing and get metrics in production. It's not to say we won't occasionally do some napkin math to make sure that we're ballpark in the right zip code for performance, but we try to stay away from writing long drawn-out RFCs because our experience has just been you have all these hypotheses about what's going to happen that simply don't come true in practice.

So simplicity above everything but correctness and production metrics above any hypotheses about what's going to matter. And that means every single line of complexity in turbopuffer has been earned. We're only going to introduce complexity if we see a performance problem in production that our customers tell us really matters. So let's rewind to the moment that we decided to bring turbopuffer into existence, the moment when turbopuffer was truly as simple as possible. And this goes back to late 2022 when our founder and CEO, Simon Eskildsen, was doing some consulting for a company called Readwise, which makes an app that helps you keep track of what books you've read. And at the time, even though Readwise was well adopted, they were spending only $5,000 a month on a single Postgres instance that was powering their entire application. They wanted to add some semantic search features so that you could find the highlights that you had left across books and you could do so semantically.

LLM powered, you know you have a rough sense of what you had highlighted in the past, you type it in and the vector magic makes sure that you find exactly the snippet that you couldn't quite recall. Great feature, worked really, really well. But in order to fit the 100 million vector embeddings that they would need to deploy this for all their customers, they would have to 6x their Postgres spend. They'd have to take that $5,000 a month bill and turn it into a $30,000 a month bill. So unsurprisingly, this feature never shipped. It was just too expensive. Readwise couldn't justify spending $30,000 a month on this one feature. But Simon, our CEO, couldn't stop thinking about this problem. If you run a little napkin math, you realize that storing a million vectors on S3 is only going to cost about a dollar a month. So for Readwise, you're talking $100 a month to store the 100 million vectors. Now, of course, you've got to add some query costs on this. But if you're talking hundreds of dollars a month, suddenly you're in business. That's the kind of investment that Readwise could afford to make on a feature like this.

So Simon locks himself into a cabin in the summer of 2023 and ships the first version of turbopuffer. And true to the napkin math, you can see that turbopuffer is $1 per month per million vectors. And queries don't end up being very expensive either, $4 per million queries. That's like as many queries as you can imagine all of Readwise users doing in a month, probably not even close to that. And as I was saying, simplicity was really at the heart of that first version that Simon built, truly applying Gall's law here. turbopuffer is essentially just putting the vectors on object storage and then having a single Rust binary that reads them off object storage. And there's a cache in the middle here, but the very first version that Simon built didn't even have the cache. It's just the binary directly reading off of object storage in the simplest way possible. And you can imagine actually the very simplest way is this completely unstructured pile of vectors. But it's pretty slow to have to search through a completely unstructured pile of vectors. You're going to have to go check every single vector.

So you can do something pretty simple to build a vector index. Like it's not actually that complicated conceptually. Obviously, the code that you write to be performing gets quite complicated over time, but the high-level concept is quite simple. You cluster the vectors that are similar to one another, and then you compute the centroid of each vector cluster. That's the C1, C2, C3, C4 before at the top. When a query comes in, you just look up in that list of centroids which of the centroids is closest, and then you go look at that one cluster. And now you're not scanning all of the data, you're just looking at that cluster of vectors. And that vastly reduces the amount of data that you have to search and gets you a reasonably performant system. Now if you have to go to object storage in every query, that's going to be kind of slow. Simon did some experiments, saw that searches were taking about a second. Not fatal, but if every search takes a second, your users probably aren't very happy. So you just throw a cache in the middle. And that cache is not important for correctness, it's just there for performance. So we're taking on a little bit of complexity, but it's earned complexity because we ran the numbers, we looked at some production data, and we saw it's just too slow to go directly to object storage. But because that cache is expendable, you can throw away that cache at any point. If the machine goes down, you need to move to another machine, you can do some cold queries in the interim, the system doesn't actually go down, it just gets a little bit slower. That makes everything really, really quite simple.

And this incredibly simple architecture scales very well. Cursor in November of 2023 migrates all of their vector search workload to turbopuffer and they save an order of magnitude on costs just as Simon's napkin math predicted. And that simple architecture, remember the only piece of complexity we've added at this point is that NVMe cache for performance, gets all the way up to 600 million vectors. And at the time that really felt like a lot. It's funny to think back on that because now relative to the trillions of vectors we have in production, it doesn't actually feel like that much. It's less than 1%, less than a fraction of 1% of all the data we have in production. But at the time getting from zero vectors in production to 600 million vectors in production was quite the accomplishment, and that initial architecture as simple as it was scaled all the way to 600 million.

Now, 2026 is not 2023. A lot has happened in the last three years. So for the rest of this talk, I want to explain, walk through how we've very carefully evolved turbopuffer, earning just a little bit of complexity at every step to meet the far more complicated retrieval needs of 2026. The biggest change we've seen is search is exploding. There's an exponential here. In 2023, most searches were driven by humans. In 2026, most searches are driven by agents. And the number of agents in the world is increasing exponentially as a function of time. And these agents aren't just doing one search, where a human might do one or two follow-up searches if they don't get the answer that they want. We've all probably used Claude code here. If you watch Claude code work, you can see it just searching, searching, searching, it'll read a little bit, it'll search a little bit more. It can easily do dozens if not hundreds of searches in response to a single user prompt. And we see that beyond coding agents too. We see that with basically any type of agent. They're doing dozens or hundreds of searches in response to a single user prompt. And those searches are also getting more complicated. It's not just vector search anymore. It's also text search. Then you need some way of fusing your text and vector results together with a re-ranker. Maybe you're doing multi-vector retrieval. Maybe you're using a search agent. So the complexity here has exploded.

So you see all of these factors multiplying together, and it makes for a really striking exponential. To zoom in a little bit on the retrieval complexity, in 2023, this is what retrieval often looked like for single dense vector searches. You'd have a human with a prompt, you'd run that prompt through an embedding model, you'd get a query vector, you send that query vector to your vector database, it sends back top 10, top 100 results. Maybe you show those results directly to the user, maybe you do another pass with an LLM to get it more of an answer style instead of a search style result. But you send it back to the human and that's the end of the pipeline. In 2026, it looks a lot more like this. You're not just doing vector queries, you're also doing text queries, you've got that re-ranker in the way. Maybe that's just one agent and you've got five other sub-agents going. Maybe the other agents aren't querying just turbopuffer, but they're also talking to your transactional system and your analytical system. And then you have some orchestrator agent that's taking all those sub-agents and synthesizing their data and then doing follow-up searches. Like that loop there, that agent loop might result in dozens or hundreds of searches.

So it's a lot. You've got agents doing more searches than ever and those searches are more complicated than ever. So our poor little turbopuffer, do we need to be worried about him? Is he getting absolutely crushed by complexity? And actually, our sense is no. This complexity has been earned. Our users aren't building these incredibly complicated retrieval pipelines for no reason. They're building them because it's actually working for their applications. Agentic AI works in 2026 in the way that it just did not work in 2023. I've seen it myself most directly with coding agents, but we hear reports from our customers across a wide variety of industries that you can actually rely on agents in 2026 to complete useful work without supervision for tens of minutes, if not hours in some cases. And the reason is that this retrieval pipeline is getting the agents, getting the models, the context that they need to actually produce useful work without human supervision at every single step. So this complexity has been earned. All of these boxes have been added by our customers for good reason, because they're seeing better results, because they're building better products.

So let's talk about how turbopuffer has continuously applied Gall's Law to make sure that at every step we're just taking on a little bit of complexity and that complexity is well-earned and justified based on the production metrics that we're seeing. 2024 was the year of scale of the core. If we rewind back to that year, turbopuffer didn't support full-text search yet. There wasn't a whole lot of re-ranking. We're kind of in that world of simple single vector retrieval that I was showing here. This is approximately what the world looked like in 2024. But we're starting to see some scale. turbopuffer that year went from 600 million vectors to 10 billion vectors, 100,000 namespaces to 10 million namespaces, 10,000 writes per second to a million writes per second. So you're seeing at least a two order of magnitude increase across a lot of important dimensions for turbopuffer. And we did this all while maintaining 99.99% availability, four nines of availability. And it required being very judicious in where we took on complexity.

In 2023, and it's kind of crazy for me to think about this, turbopuffer would just throw away the existing vector index whenever too many writes built up. If you had a 10 million vector index, turbopuffer would cluster it like I was explaining earlier. And then it would search over those 10 million vectors whenever a query came in. And as you wrote more vectors, it would keep them off to the side and search those too. But at some point, it's got to fold those vectors that are sitting in the write-ahead log into the main index. And the simplest possible thing you can do is throw away the index. Forget that you've ever seen any of those 10 million vectors before. Just say, hey, I got a pile of 11 million vectors. Let's start from scratch. That worked reasonably well when there were only 600 million vectors in the system. But with 10 billion vectors, that starts to fall over. It's a disaster to have to throw away all that work just because you got a new handful of vectors. So we introduced incremental indexing. And this was pretty complicated. We had to pretty thoroughly consider the ramifications here because it required a new vector clustering algorithm and a vector indexing algorithm called SPFresh. The idea is you've already got all these vectors nicely clustered. Why throw that away? Just take the vectors that you're adding and take the vectors that you're removing and smush them into the vector space that you've already got. And as you do this, the centroids are going to move around, so now you've got to do a new pass and figure out what your new centroids are. It's really delicate, finicky code. But if you do it right, you're only paying cost relative to the amount of vectors that are added. You're indexing time scales relative to the number of vectors that you're writing instead of the total number of vectors that you have. And this takes you from n squared complexity, which for large indexes just absolutely blows up, to linear complexity, O of n. And that's what allows turbopuffer to scale beyond 10 million vector namespaces into the hundreds of millions, if not billions of vectors. But this was quite a bit of complexity that we had to very carefully consider.

And when you go to update an index on S3, you start to run into performance problems. In the 2023 world, it's very easy. You have a bunch of files, one per cluster roughly, and you just blap those out to S3. You just do a couple put requests. In 2024, you have all these random updates. Cluster one has some new vectors. Cluster two has some vectors that are removed. Cluster three maybe got split in half and those files need to be shifted. How do you do that efficiently? S3 doesn't support random writes. So what you have to do is you build a log-structured merge tree on top of S3, which might be a concept some of you are familiar with. RocksDB is a famous log-structured merge tree. They're used in basically every database. But these log-structured merge trees, these LSM trees, are all designed for disks. And turbopuffer is object storage native. Our only source of truth is S3. So we had to write our own LSM tree that's optimized for S3. And the big difference there is you work with much larger blocks. S3 is really slow when it comes to actually putting an object or getting an object. You can do lots of them in parallel and get really good throughput, but it's very high latency. So you have to work in these massive chunks. And we couldn't find anything off the shelf that supported that. So we had to build our own object storage native LSM tree. But we had evidence from Cursor and some of those original early customers that the current indexing strategy was not working. And that's why we were comfortable taking on this fairly substantial bit of complexity.

The other problem we ran into in 2024 was the problem of filtering. It turns out to be very difficult to combine vector search with filters. And if you imagine you're building a coding agent, a very, very common query you need to do is filtering by path. You might have some knowledge based on a prior search you did or based on what the user told you that there's a particular module that's involved. And you only want to find, say, authentication code that's outside of the authentication module. You want to see where the authentication module is being used. So you do a glob query. When you restrict yourself to looking at, imagine here the vectors are functions in the code base, you restrict yourself to looking at vectors that match this path. Naively, if you use the vector index here, you can see this query vector isn't close to any of the vectors that match the filter. You can imagine all those minuses are functions in the authentication module, and those pluses are the mentions of authentication outside of the authentication module. So if you just use the vector index and find the 10 closest vectors to Q, you're going to find a bunch of minuses and then you're going to apply the filter and you're going to go, shoot, I didn't find any results, and your recall will be 0% and your users will be unhappy because they didn't get the search results that they were looking for. The other thing you could do is find everything that matches the path and then find the closest vectors. But if you do that, you're not using the vector index anymore. You have to exhaustively scan everything that matches the path. That might be 95% of the vectors in the index. So you're going to have terrible performance if you do that. So we had to introduce what we call native filtering. And for every cluster of vectors in turbopuffer, remember, behind the scenes, we've sorted all these vectors into clusters. For every cluster, we keep track of whether there's anything in that cluster that matches the filter. And now we can look at our attribute index when we go to apply this glob filter and say, hey, we're looking for things in this foo source path. What clusters could possibly contain a vector that's relevant? And we can see foo/readme.md, that's in zero/one, but foo/source/main/bar, those are in five and four. So when we do the vector search, we can restrict our attention to, say, the top 10 vectors in cluster four and five, and we'll actually get the vectors that we were looking for, and we'll get them in a time frame that's reasonable because we're not scanning over all the vectors, we're still able to leverage the vector index.

So as these indexes grew in size, we saw that this was a pain point, we saw that filtered queries had an unacceptably high latency. And we felt justified in adding this bit of complexity. Now we get to 2025, and single vector search is no longer enough. Our users start asking for more traditional search techniques, like full-text search. And the reason we see full-text search come up is sometimes you know exactly the keyword that you're looking for. If you want to find things related to Taylor Swift and specifically Taylor Swift, you don't accidentally want to pull in a bunch of things related to country artists. And if you do a vector search, that vector for Taylor Swift is going to be really close to vectors for other country singers, and you might sweep up more results than you want. So there's still a very real use case for full-text search. You can see it with coding agents too. If there's a function that you're looking for, you don't want the exact name for that function. You don't want functions that sound sort of similar but are actually unrelated coming up in the search.

And true to our roots, we started with the simplest possible version of full-text search. You can see V1 here performed pretty well for simple queries like San Francisco and United States Constitution, but for long queries, it started to fall apart. And we were a little surprised to see these long queries at first. Like, what human is searching for pop singer-songwriter born 1989 blah blah blah blah blah? And it turns out agents, when they use full-text search, really like to be verbose, which we don't Google like this, but the data that we saw in our production metrics showed agents were doing all sorts of keyword searches like this. So we implemented a special algorithm in turbopuffer called MaxScore, which is a form of dynamic pruning that allows you to skip terms that are common. And the way full-text search works is you score every document based on the terms that it contains, and terms that are rare contribute more. So singer-songwriter are probably more rare than year, and certainly more rare than of. So once you've gotten enough documents that contain singer-songwriter, you know those are going to be in the top 10 or the top 100 or whatever you're looking for. You no longer need to think about of or the or year, and you can just stop worrying about the documents that only contain of or the end here, and that vastly speeds up the search. So you can see for those long agentic style queries, we were able to get the time down from 175 milliseconds, which is tolerable but not great, down to 20 milliseconds.

And this is a great case study of we started with a simple thing, and if we had gone with complexity from the start, we would have used a different algorithm than MaxScore. There's something called WAN that's been industry standard for years, but WAN does dynamic pruning in a way that's more optimized for the short phrases and not the long phrases. So we avoided a lot of time working on an algorithm that would not have served us well in this new AI-powered world. Scale continued to be a problem through 2025, but we were able to employ what I think is just a phenomenally effective trick. We got asked by one of our customers to support a 100 billion scale. Now, I say turbopuffer has 600 million vectors in production at the end of, or sorry, 600 million vectors in production at the end of 2023. That grew to 10 billion. 100 billion was larger than the total amount of vectors that we had in production in 2024. This is a massive use case for us. And to have to search over all of those vectors at once really stresses the system. But you can break a 100 billion problem down into 101 million sized problems, and you can just shard that index and do 100 searches every time a query comes in. And I want to downplay the amount of work that went into optimizing each one of those 1 billion scale namespaces that did stress turbopuffer a fair bit. We had to roll out quantization of vectors to decrease the amount of memory required for each vector so that we could rip through more vectors within that 200 millisecond budget. But this simple trick of just being able to recruit 100 machines for a single search meant that we were able to go effectively overnight from a 1 billion scale use case to a 100 billion scale use case. And this is a real testament to that core of turbopuffer being so simple. Because everything is on object storage, it's very easy to just throw more machines at the problem. When everything is spinning disks and every machine has a fixed amount of disk space and you need to worry about how you're allocating compute to those disks, it's very hard to do this kind of sharding. But with turbopuffer, all the data is going on S3, and if you need more machines to handle the scale, you can just throw more machines at the problem.

And we've seen more and more use cases since 2025 pushing up against these crazy high limits for things like web search and doing reinforcement learning when you're training models. And now 2026, the present. What we've seen is an absolute explosion from these agents. This is a chart published by GitHub about the record number of pull requests that are merged, commits that are generated, repos per month that are created. And you can see the exponential pretty clearly in every one of these graphs. And we see it in our metrics as well. We now have four trillion documents in production. The scale is absolutely staggering, and the growth rate suggests that it's not going to stop anytime soon. We're seeing over 25,000 searches per second, over two and a half million writes per second. And we see a real diversity in use cases. We're not just for coding agents and productivity tools now. We're seeing adoption in legal. We're seeing adoption in healthcare. We're seeing adoption in financial services. So we're really seeing vector search at the heart of a lot of different applications for AI. And turbopuffer has gotten more complicated in order to support all of these use cases. It's not just single vector retrieval anymore. We do sparse vectors. We do BM25. We do regex searches. And we have a variety of different deployment models to support these various use cases.

I want to talk a little bit about two of the most exciting developments that we're seeing in 2026. One is search models, and these are specialized models for searching things really well. And if you remember, this is what a lot of retrieval pipelines look like now in 2026. But the thing is, people are hard coding these rules. If you crack open the Claude code source code, if you look in what our customers are doing in their retrieval pipelines, it's a bunch of rules about if the query looks like this, do a vector search and a text search and then use this re-ranker. But if it has this other configuration, maybe skip that step and just do a vector search. And then you have the LLM maybe spit out whether it should do a follow-up search. And you have to write a lot of this by hand. And because this is the era of AI, we can just train a model for that. We're partnering with a company called SID that's trained a very interesting model called SID1 that just learns how do you search tools? It knows when it should use keyword search. It knows when it should use vector search. It knows when it needs to do a follow-up. And what you can see already is if you let SID loose with high thinking mode essentially, 4x, you get better retrieval than you do with something like GPT. And if you let it run in normal mode, this isn't pictured here, but you can see the performance is competitive. You get equivalent performance essentially from SID1 and GPT 5.1. But SID1 ends up being a lot cheaper because it knows I don't need to do five searches for this query. I can just stop as soon as I've gotten the first search, which has the answer that I'm looking for. So we're really excited about the prospects of these models because they bring down costs for the easy cases, but they also allow you to max out for the hard cases where you really want to get the right answer, where you're generating a report that's going to be really material for your customer, for example.

turbopuffer hasn't had to evolve to support this. This is a real case of simplicity scales, and that's been really exciting to us. We've been able to let the ML researchers design these models, and they just use the core tools. All of these things I just mentioned, it's kind of hard for a human now to know which of these to use, but the models are really good at just learning which one of these tools, which type of search is best for a given user prompt. So the core of turbopuffer is just scaling for this new era of search models. And we'll see at some point maybe these search models become the bread and butter of every retrieval pipeline and we'll think about integrating them into the core product. Somewhere where we did have to invest a little bit in complexity is branching. With this agentic explosion, it also means costs are exploding a little bit, and we wanted to find a way to bring costs back down. And if you think back to 2023, 2024, often with a coding agent, for example, you would have one checkout of a repository per human, and then you would index that copy of the repository inside of turbopuffer. And the simplest thing is just every person gets a full copy of that repository in turbopuffer. Now, this is pretty wasteful because if you think about it, my Git clone and your Git clone are going to be 98% the same data, except for that last 2% where I'm working on one feature and you're working on a different feature. So having a separate copy of that index in turbopuffer works totally fine at human scale. But when you throw agents into the mix, when you have dozens and dozens of agents for every single person and each one of those agents has a copy of the repository, that ends up being a pretty substantial amount of data that you have to store in turbopuffer and a lot of wasted work re-indexing all the same functions and building all those vector indexes for basically the same data.

So we recently rolled out, literally last month, support for branching. So you can take a vector index that you're happy with. Just like a Git repository and fork, make a branch, and that requires absolutely no re-indexing on turbopuffer's side. It's just a metadata update. It's really fast. It's really cheap. And now you have two pointers into the same vector index, but they can evolve independently. So as you start writing data to the new branch, it doesn't impact the data in the original branch. So for things like coding agents, this has an obvious application. We've actually seen since we launched this just a month ago, we already have one petabyte of data in branch namespaces, just a staggering scale. But we're also starting to see this be really useful for reinforcement learning, where you're doing searches as part of training a model. And you get into a state that you really like. The model's going down a good path and you want to run more experiments off that path. You can just create a branch in turbopuffer and then let your RL environment go down a couple different explorations based on that branch. And that way you don't have to pay the cost of constantly re-indexing every time you want to do a new RL exploration.

But what does the future hold? We're not entirely sure where every table is going to go in 2027. We have some hypotheses, but one of our core beliefs at turbopuffer is that this is a time of great uncertainty and you don't want to look too far into the future. You want to focus on just the next couple steps. So here's what we see in 2027 likely to develop. We think there's going to be a bifurcation in workloads. This explosion can't continue forever for every search. There's only so many VC dollars in the world. You're only going to be willing to spend so much on tokens in response to every single user search. So we think on one end there's going to be the cost admitting. You're going to look for the queries that are really easy and you're going to try to run those as cheaply as possible. This is maybe your everyday issue search or a really simple coding prompt or whatever it is that's just you're running tens of thousands or hundreds of thousands of these operations and you need to make sure the economics work. This is the bread and butter of turbopuffer. It's what we've been optimized for from the beginning with the way we automatically cache on S3, now with branching, now with search agents that know when to stop searching. And we've got a couple more features that we'll be rolling out like int8 vectors that are smaller, literally half the size of F16 vectors that can halve your storage cost, literally cut your turbopuffer bill in half. So we're going to continue pushing on this cost meeting so that you can scale your applications across this agentic explosion without scaling your costs to something that would be ruinous.

But we also see a lot of perfmaxing. As these agents get better, they are increasingly being deployed in these situations where you're going to spend potentially tens of thousands of dollars on human salaries to produce some sort of legal brief for a contract or a medical diagnosis, and it's worth spending hundreds or thousands of dollars on tokens to get the right answer. So we're keeping a close eye on the retrieval techniques that are evolving so that we can make sure that if you want to spend more dollars getting better answers out of your agents and doing more searches and getting more precise search results, turbopuffer is there to support it. We just launched support for sparse vectors, which are kind of a hybrid between dense vectors and keyword search. We've got this burgeoning partnership with these search agent models. And we've got some really interesting features that allow essentially just doing more search. Late interaction allows you to, instead of doing a single vector search, search with dozens of vectors at the same time. And you see better performance with this on some limited benchmarks, but there's more work that needs to happen academically before this is really a viable technique. But we're keeping a close eye on it in turbopuffer so that if that does become the dominant retrieval paradigm, our customers do indicate that this is resulting in huge improvements for their workloads, that turbopuffer can support those workloads.

And truly, turbopuffer has evolved in partnership with our customers. We are always looking for the pain points that our customers are running into, whether it's going to be because costs are too great on the cost meeting side or because the retrieval performance, the quality of the search results that are coming out is too low. To go back to retrieval in 2026, this is our rough sense of how it breaks down. On the right side of the diagram, you can see those are the cheap and easy queries. That's turbopuffer's bread and butter. That's where leveraging S3 and caching has enabled us to keep costs down. We'll continue investing there. And then you can see this frontier of the searches that count, where we're very carefully taking on complexity, but only when it's earned, only when our customers tell us, no, this technique is essential. And I'm tired of handling the infrastructure myself. I want you to build this into turbopuffer. And you can see that frontier is steadily advancing. And we expect that pattern will continue into 2027 and beyond.

So the takeaway I want to leave you all with is that you shouldn't let your search infrastructure hold back your product ambition. We're seeing that our customers are getting incredible leverage out of not just the models, but also the harness they put around those models to build AI applications that actually work in 2026. And that's putting a ton of pressure on the search infrastructure. And every day we wake up and we ask ourselves, how is turbopuffer holding back our customers' product ambition? What features aren't they building because turbopuffer is too slow or too expensive or not providing accurate enough results? So we don't know exactly what the future of retrieval holds, but we're super confident in this approach of earning every line of complexity to make sure that we still have this very simple cost-effective core, but we're providing the increase in quality as search retrieval evolves as a field. So that's what I got. Thank you all very much.