Address and POI are separate first-class surfaces
Exact address, typeahead, fuzzy address, POI name, category, type, and chain each have dedicated lookup paths. They do not share a single text index with different query strings bolted on.
Location search is one of those problems that looks solved from the outside. There are geocoding APIs. There are mapping platforms. Every major product with an address field has something. The category feels crowded.
The problem shows up when you try to build something real on top of one of those services. Search results come back as IDs you still have to hydrate somewhere else. The API treats "3301 Stirrup St" and "Starbucks near downtown" the same way: text in, heuristic routing, ranked list out. If you want to bias results toward a user's history or preferred categories, you get a flag parameter and a black box behind it. You can't inspect what it's doing or audit why ranking changed.
The deeper issue is architectural. Most geocoding services are general search engines — text indexes with location adapters bolted on. That design works at the marketing level. It starts breaking down when you need reliable intent separation, payload-complete results, or transparent personalization that your team can actually reason about.
We needed a location surface that could handle this cleanly. One that knew the difference between an exact address, a typeahead fragment, a POI name, and a raw coordinate at the routing level — not as a heuristic on top of a text search, but as a real architectural boundary. And one where personalization was an explicit input you could see and control.
The design decision that makes it different: commit to the fixed surface at build time. If the production API will serve exact addresses, typeahead fragments, POI lookups, coordinate queries, reverse lookups, and nearby results — and that surface won't change — then you can compile the semantics for each into the runtime artifacts themselves instead of reconstructing them on every request.
Each intent gets its own lookup path. Result payloads are encoded into the index at build time, so serving them is targeted binary lookup over memory-mapped data instead of source-row hydration and on-the-fly serialization. The custom HTTP parser handles only the fixed API surface. The request path stays small because it never pretends to be a general search engine.
Personalization follows the same principle. Instead of an invisible bias applied somewhere in the stack, profiles are explicit tokens you create and pass. They encode categories, chains, prior places, examples, and context in a portable, inspectable format. The ranking intent is legible to the team building on top of it.
Exact address, typeahead, fuzzy address, POI name, category, type, and chain each have dedicated lookup paths. They do not share a single text index with different query strings bolted on.
A raw lat/lon query routes to reverse address first, then falls back to nearby POI. Reverse and nearby are real surfaces, not text search adapters that happen to accept a coordinate.
Preferred categories, suppressed chains, prior places, examples, and destination context compile into a portable token. You create it, pass it, and can inspect exactly what it says.
Responses carry labels, coordinates, typed nested payloads, route names, scores, and match metadata. Not IDs you still have to hydrate from a second service.
Market frame
Mapping platforms and hosted geocoding services occupy one end of the spectrum: rich features, fast to start, but opaque internals and the parser — or in this case the ranking and routing logic — lives somewhere else. Roll-your-own search adapters sit at the other end: flexible but expensive to maintain and brittle at the edges.
We think about the space along two dimensions: how explicit the intent model is (does the service distinguish address from POI from coordinate at a routing level) and how transparent the personalization is (can you see and control what biases ranking).
Competitive landscape
Mapping platforms
Google Maps, Mapbox, HERE
Rich UX. Generic text search routing. Personalization is a black box. Results often require hydration. Platform lock-in baked in.
Where we're building
Explicit intents, transparent profiles
Each intent is a real surface. Profiles are explicit tokens. Results are payload-complete. The architecture matches the actual surface.
Geocoding APIs
Nominatim, Pelias, hosted geocoders
Good for address resolution. Usually a text search with location filters. POI and intent separation are typically weak. Personalization rarely exists.
DIY Elasticsearch/Typesense
Custom index, custom pipeline
Flexible on day one. Intent separation is your problem. Personalization is your problem. Performance at scale is your problem.
HTTP JSON peak
172,304 QPS
1.48ms average · complete payloads
Binary protocol peak
1.5M QPS
No HTTP layer · same production payloads
Batch peak
21M+ QPS
Binary batch · bottleneck is transport, not the data-path
HTTP JSON
Complete payloads: labels, coordinates, typed address or POI data, match metadata, scores. Not an integer stub. The request path has no general search engine — each intent routes directly to its compiled lookup.
Typeahead implication
At 1.48ms per lookup, predicting the user's next two keystrokes and pre-fetching is cheaper than waiting for a second round trip.
City
1.48ms avg
172,304
Feature / landmark
1.50ms avg
169,766
Address typeahead
1.50ms avg
169,377
Airport
1.51ms avg
168,427
Address exact
1.52ms avg
167,330
POI chain
1.56ms avg
163,106
Nearby POI
1.73ms avg
147,444
Coordinate auto-intent
1.82ms avg
139,880
Profile create
2.08ms avg
122,465
Measured with oha, production verification enabled, 5 seconds per route, 256 connections. All runs returned 100% HTTP 200. Responses include complete typed payloads.
Binary protocol
When HTTP parsing overhead is the ceiling, the binary protocol over socket removes it. Same production-shaped queries, same complete payloads. Aggregators, internal pipelines, real-time ranking layers.
Airport
1,533,658
Feature / landmark
1,518,215
City
1,476,504
Address typeahead
1,444,994
Coordinate auto-intent
1,360,469
Nearby POI
1,019,321
Address exact
1,001,704
POI chain
933,921
Profile create
715,446
Batch API
Send hundreds of lookups in a single call. At batch scale, the search work — index lookup, payload retrieval, response assembly — completes before transport overhead even starts. The bottleneck shifts entirely to the wire.
Geocoding pipelines, bulk address validation, offline enrichment jobs, and high-throughput ranking layers all belong here. You get full typed responses on every record, not just IDs.
JSON batch
Parallel multi-intent
Send a mixed array of address, POI, reverse, and nearby lookups in one request. Each item resolves independently.
Binary batch
21M+ QPS
Frame encoding eliminates per-request HTTP overhead entirely. At this throughput, transport is the only thing left to optimise.
Surfaces
Most location APIs expose one endpoint. The service figures out what you meant from the query text. That works for demo-grade use. When you need reliable behavior at production scale — or when you want the client to be explicit about intent — it breaks down.
Locate API exposes the full intent surface. Exact address, typeahead, fuzzy address, POI by name, category, type, and chain, city, airport, landmark, reverse address, nearby POI, and coordinate auto-routing are all real paths, not heuristics.
Search modes
search (auto) Routes intelligently across exact address, fuzzy address, POI, entity, and coordinate auto-intent. Correct for most product surfaces.
typeahead Address typeahead with compact fast-path lookup. Tuned for keystroke-latency UX.
poi · poi_name · poi_category · poi_type · poi_chain Explicit POI locality surfaces. Search by name, business category, business type, or specific chain.
city · airport · feature Named entity lookups: cities, airports, and geographic features or landmarks. Direct lookup paths, not search adapters.
nearby · reverse Explicit spatial routes. /nearby and /reverse endpoints accept lat/lon directly. The auto-intent path inside /search also routes coordinate queries here automatically.
Exact address, typeahead, fuzzy address, POI name, category, type, and chain each have dedicated lookup paths. They do not share a single text index with different query strings bolted on.
A raw lat/lon query routes to reverse address first, then falls back to nearby POI. Reverse and nearby are real surfaces, not text search adapters that happen to accept a coordinate.
Preferred categories, suppressed chains, prior places, examples, and destination context compile into a portable token. You create it, pass it, and can inspect exactly what it says.
Responses carry labels, coordinates, typed nested payloads, route names, scores, and match metadata. Not IDs you still have to hydrate from a second service.
Response shape
Every response includes the route that was taken, so you know exactly which intent fired. Results carry typed nested payloads — address records, POI records, city or airport objects — not just a label and a coordinate.
{
"route": "address_exact_direct",
"latency_us": 42,
"results": [
{
"type": "address",
"label": "3301 Stirrup St ...",
"lat": 43.850201,
"lon": -104.211334,
"address": {
"number": "3301",
"street": "Stirrup St",
"land_use": "residential"
}
}
]
} FAQ
Short answers for teams evaluating Locate API.
Most geocoders are generic search engines. Locate API is a location service built around a fixed set of real production intents: exact address, typeahead, fuzzy, POI by name/category/type/chain, city, airport, landmark, reverse, nearby, and coordinate auto-routing. Each has its own lookup path.
The runtime artifacts are compiled to serve the fixed production surface directly. Result payloads are preencoded, lookup tables are direct binary layouts, and ranking signals are embedded at build time. The request path does not run a general search engine on each query.
HTTP JSON routes measure roughly 120K–172K QPS with average latencies under 2.1ms on a production-shaped payload. High-throughput binary transports exceed 1.5M QPS on several routes, and batch paths push into the tens of millions.
A portable, inspectable token you create via /profile or /search with profile_create mode. It encodes preferred categories, suppressed chains, prior places, examples, and origin/destination context. Pass it on any subsequent search call to bias ranking.
The Labs playground is the public face of a production runtime. If you need address and POI search with explicit intent routing, profile control, and real payloads, email us. We will tell you what is ready, what is still moving, and whether it belongs in your stack.