Announcing altengine: App Engine's Search, Channel, and Datastore, semantics intact

Three of App Engine's most useful services — Search, Channel, and Datastore — are what we're launching with today. Two of them were retired years ago; the third is still around, but stricter than it needs to be. All three are now standalone cloud services: the semantics you knew, over a clean REST API, on a runtime built for how the web works now.

Why bring back a deprecated API?

App Engine's legacy Search and Channel APIs were quietly great. Search gave you managed full-text indexing with a real query language, facets, and ranking — no cluster to run. Channel gave you a simple way to push realtime messages to clients, without wiring up your own socket infrastructure. Both were well-documented and priced for small apps.

When they were deprecated, the migration paths were heavier, more expensive, or simply different in shape. Plenty of working software was left to either rewrite around a bigger system or freeze.

And in the years since, nothing cheap has really filled the gap for search. The usual options are either running and paying for your own search cluster, or a hosted service whose price climbs steeply once you get past a thousand documents. For a small app, both are overkill. altengine is for everyone who thought: I just want that API back. (We'll dig into the comparison in a future post.)

And why a Datastore, when that one never went away?

Datastore is the odd one out here: it wasn't retired. But anyone who shipped real software on it remembers the sharp edges. Entities weren't arbitrary JSON — every property carried a declared type, and nesting meant reaching for embedded entities. Joins didn't exist, so you denormalized your data or paid for a second round trip. Composite indexes had to be declared up front, and get it wrong in production and the query simply failed. Outside an entity group, queries were eventually consistent, which is a genuinely hard thing to reason about at 2am.

Those constraints bought something real: queries that stayed fast at scale, and a bill that didn't surprise you. But a lot of them were the price of a much older storage engine, not laws of nature. So we kept the parts people liked — the document model, the bounded query engine, no cluster to size — and loosened the contract everywhere it used to pinch:

  • Any JSON object. Put in whatever shape you like. Objects nest freely, there's no schema to declare, and no property types to pick in advance.
  • Joins. Attach a referenced document from another collection to each result. The lookup is by the foreign collection's key, so a join is always index-served and bounded by your page size — never a hidden full scan.
  • Grouped aggregates. count, sum, avg, min, and max over a filtered set, without reading every document yourself.
  • Strongly consistent reads. A namespace always reads back the latest committed write. There are no entity groups to design around.
  • Indexes that don't block you. No index file to maintain. By default, a query needing an index it doesn't have gets one — the engine builds what it would have suggested and runs your request, rather than failing on you mid-build.

That last one cuts both ways, so it's a switch rather than a rule. Auto-indexing is never silent: the one-time build is billed as writes, and the response hands back an auto_indexed field naming exactly what it created. And in production, convenience is usually the wrong default — you want to decide which indexes exist rather than let a stray query create one, since every index adds a write per document and takes storage. So you can turn it off per instance, and an unindexed query returns 400 INDEX_REQUIRED naming the field to add instead.

What we kept is the bound that earns its keep: a query has to be index-served, and reads are metered by the rows they examine. That's what keeps a query fast and its cost predictable — the fast query and the cheap query are the same query.

For Search and Channel, then, parity of semantics is the contract — the concepts and the query language you already know, unchanged. For Datastore, it's the familiar model with a deliberately looser contract.

What's launching today

Search API

Create an index, put structured documents in, and query them with the operators you already know. Text, atom, number, and date fields; fielded queries; facets; sorting; and pagination. The query language stays faithful to App Engine's Search syntax, so your existing queries mostly just work.

POST /v1/search/my-shop/ns/_default/idx/products/search
    ?q=title:jacket AND price < 150
    &facet=tags&sort=price&limit=20

Channel API

Publish messages from your backend over plain HTTP; clients subscribe over a single WebSocket — one socket can carry many channels — and receive fan-out in realtime. You're billed on the messages delivered and the time subscribers stay connected, so a channel with no one connected costs nothing.

POST /v1/channel/my-shop/publish

{ "channel": "orders",
  "data": { "id": "sku-1024", "status": "shipped" } }

Datastore API

Put arbitrary JSON documents in, then filter, sort, join, and aggregate them with a bounded query engine — no SQL, no schema to declare up front. Documents live in namespaces, isolated stores you create on demand, which makes one-database-per-tenant the easy path. Transactions are atomic, with field-level increments that never lose an update, and every namespace has 30-day point-in-time restore at no extra charge.

POST /v1/datastore/app/ns/acme/col/orders/query

{ "where": [{ "field": "status", "op": "=", "value": "open" }],
  "order": [{ "field": "__updated__", "dir": "desc" }],
  "limit": 25 }

What makes it different

We treat parity of semantics as the contract: the query language, field types, facets, and sorting behave the way you remember, even though you're calling them over REST rather than a language SDK. Three things guided the rest:

  • No idle cluster. Unlike cluster-based search, there's nothing running to pay for when you aren't using it — you're billed for the storage your documents and index use, plus the searches you run.
  • Realtime, billed to match. Publish over HTTP and subscribe over one WebSocket that carries many channels. You're billed on message deliveries and connection time, so cost tracks real usage — and a channel with no one connected costs nothing.
  • Queries that can't surprise you. Datastore queries are index-served, and reads are metered by rows examined — so the fast query and the cheap query are the same query. Missing an index won't block you while you build (one gets created for you, and reported back), and switching auto-indexing off in production puts you back in full control of what exists.

Pricing that starts at zero

There's one plan — pay-as-you-go — and the first $3 of usage every month is free for every organization, shared across whatever services you use. Search is billed on queries and on storage for your documents and their index (index storage counts only the content you push, so it stays cheap — and there's no idle cluster to pay for); Channel is billed on message deliveries and connection time; Datastore is billed on writes, reads, and stored data, with indexing as the lever you control — every index you declare adds a write per document, and a namespace you aren't using costs only its storage. No seats, no minimums, and no card required to start. See the pricing page for the rates.

Getting started

  1. Create an organization in the console.
  2. Generate an API key with a grant for Search, Channel, Datastore, or any combination.
  3. Call the API over REST — your existing App Engine queries and document schemas carry over as-is.

If you were using App Engine's Search or Channel service before, the concepts all transfer: what you're writing is the call layer, not a new search design.

What's next

These three are the first services, not the last. The platform is built to add more managed services in the same spirit — reviving retired APIs and offering standalone takes on App Engine–style capabilities — as demand shows up. If there's an API you miss, tell us — it helps us prioritize.

Start free in the console

← Back to the blog