# altengine > altengine offers simple, App Engine–style managed cloud services: full-text Search, realtime message Channels, a JSON document store (Datastore) with a query engine, Auth — end-user accounts and identity tokens with row-level access rules, so a browser app can talk to Datastore and Channel directly with no backend of its own — Functions (sandboxed JavaScript on its own URL), Blob (object storage with free bandwidth), Containers (a Docker image run as a background job), Automation (your own scripts on your own Windows machines), and Static (hosting for the built front end that calls all of it, with bandwidth that is not metered). Search and Channel are faithful revivals of App Engine's retired APIs: the semantics (query language, field types, facets, sorting) are preserved, but they are reached over altengine's own REST/JSON API rather than App Engine's language SDK, so migrating means rewriting the call layer while queries and document schemas carry over. Datastore was never retired; altengine keeps its familiar document model but loosens the contract — any JSON object (no declared property types), joins, grouped aggregates, and strongly consistent reads. Auth is not a revival: App Engine leaned on Google accounts, whereas Auth gives a tenant their own end-user population. There is one pay-as-you-go plan: the first US$3.00 of usage each month is free for the organization, shared across every service, and everything above it is metered per request. altengine starts with these App Engine–style services but is not limited to them — the platform is built to add new managed services as demand grows. altengine is an independent project and is not affiliated with Google. ## Services - Search API: managed full-text search. Structured documents (text, atom, number, date fields), a query language faithful to App Engine's Search syntax, facets, sorting, and pagination. Billed on queries plus the same axes as Datastore — reads, writes, and stored data: queries are a flat $0.50 per 10,000 search requests; reads meter the work a query does on top of that, by rows examined (one read = up to 100 rows; a selective query is a read or two, and a repeated query served from cache bills zero reads — just its query); writes are metered by rows written (putting a document writes its row plus its index rows; deletes bill as the rows they remove; deleting an index is free); and stored data covers documents plus their index; there is no charge for idle capacity (no cluster to keep running). - Channel API: realtime pub/sub. Client WebSockets (one socket carries many channels) authenticated with short-lived, channel-scoped tokens; publish over HTTP (server-side) or, with a publish-capable token, over the client's own WebSocket (per-connection rate-capped); fan-out to subscribers. Clients open and manage their own WebSocket connection. Billed on message deliveries and connection time; a channel with no open connections costs nothing. - Datastore API: a managed JSON document store with a Datastore-style query engine. Documents are arbitrary JSON keyed by a string (numbers accepted, stored as their string form) or an auto-generated id (uuid, scattered, serial, or manual); namespaces (isolated stores up to 10 GB) hold collections. Structured queries (multi-field filters, sort, keyset pagination, ids-only responses), grouped aggregates (count/sum/avg/min/max), batch get by keys, atomic transactions with field-level increment, declared single-field and composite indexes (a query must be index-served; auto-indexing is on by default, so a query needing a missing index has it created and runs anyway — reported in the response as auto_indexed and billed as writes for the one-time build — and can be turned off per instance to get 400 INDEX_REQUIRED instead, which is recommended in production), and 30-day point-in-time restore. Billed on documents written (rows), reads, and stored data; no charge for idle capacity. - Auth API: a managed end-user identity provider for a tenant's own app users. Public, browser-facing endpoints under /v1/auth/{instance} (no organization API key — the end user's credentials are the trust boundary): config, embed.js, signup, signin, token/refresh, signout, me, passwordless start/verify, password reset start/verify, 2FA TOTP start/confirm/disable and 2fa/verify, passkey register and login start/finish, and passkey list/delete. Four sign-in methods: password, passwordless emailed one-time code, TOTP two-factor, and passkeys (WebAuthn). A successful sign-in returns { id_token, refresh_token, expires_at, refresh_expires_at, user }; with 2FA on, signin returns { mfa_required, mfa_token } to exchange at /2fa/verify. The id_token is sent as `Authorization: Bearer ` to /v1/datastore/... and /v1/channel/..., so a browser or mobile client reaches those services directly with no backend of the tenant's own. The sign-up form is configuration: the instance declares which fields to collect and which one is the unique login identity, and every other field becomes part of the user's profile (self-asserted). A user's identity data is split into two bags: profile (what the user typed at sign-up, read as $auth.profile.X — self-asserted, safe to display or stamp but NOT authoritative) and claims (server/admin-set only via the console or admin API, read as $auth.claims.X — authoritative, safe to authorize on; a user can never write claims). Gate access on claims, display profile. Row-level access rules on the auth instance (keyed "datastore:" / "channel:") set a level ceiling plus per-collection read (public | authenticated | a filter list), create (stamp server-set fields), update (match guard + immutable fields) and delete (match guard); values may use $auth.uid, $auth.identifier, $auth.email, $auth.claims.X and $auth.profile.X placeholders that resolve only from the verified token, and anything not listed is denied. Channel entries list templated channel patterns and mint subscribe-only tokens. Other settings: allow-signup toggle, browser origin allowlist, CAPTCHA, per-method toggles, token TTLs, and an email From name. Auth endpoints are rate limited (about one request per second per client) and /start endpoints never reveal whether an account exists. Billed on sign-ups, sign-ins, and stored users (a monthly average of the account count). - Functions API: sandboxed JavaScript on its own URL, with capability-scoped clients for the other services bound per function by a grants map, secrets, an outbound allowlist, CORS, cron schedules, error groups and a live tail. Deploys are immutable versions and rollback is a pointer move. Billed on invocations, CPU time, and a flat monthly charge per deployed function that accrues whether or not it is ever called; calls a function makes to Datastore, Search, Auth or Channel meter on those services at their normal rates. - Blob API: object storage. Files are uploaded straight to storage through a short-lived signed link (multipart past 5 GB), referenced elsewhere by a blobkey, and optionally published on a subdomain of their own. Billed on stored bytes (sampled hourly and averaged over the month), uploads, writes and lists, and reads. Bandwidth is not metered at all, and a public file served from edge cache is not billed as a read. - Containers API: run a Docker image as a background job for as long as the work takes, in one of three sizes, with a completion callback, an image allowlist, and per-instance limits on runtime, concurrency and cost. Organization API key only. Billed on the time a machine actually ran — scaled by size, so a second on a large counts as twelve on a small — plus a fee per job; nothing accrues while an instance is idle, because there is no machine when there is no job. - Automation API: run your own scripts on your own Windows machines to drive desktop applications and firewalled portals, on a schedule or on demand, through a small agent the machine enrols. Organization API key only. Billed on the time each enrolled machine spends connected, a fee per run started, and the time runs spent executing. A run's files are objects in a blob instance the fleet owns and are billed by Blob, not on an automation line of their own; setting a machine up — installing VirtualBox, fetching Windows media, building a guest — is not billed and does not count against the run's cost ceiling. Each instance carries a per-run cost ceiling, and the machine stops a run when its budget is spent, so a script with no time limit still cannot overspend. - Static API: hosting for a built front end. Deploy a directory (`altengine static deploy ./dist`) and it is served from a subdomain of its own with bandwidth that is not metered. Files are content-addressed, so a redeploy uploads only what changed; every build is kept and activation is a pointer move, so publishing an earlier build is instant and uploads nothing. Path resolution covers directory indexes, a 301 from /docs to /docs/, clean URLs (/about serves /about.html), an optional SPA mode that answers unmatched paths with index.html and a 200, and a custom 404 page otherwise. A file whose name carries a content hash (at least eight alphanumerics including a digit, before the extension) is served immutable for a year; everything else revalidates against a content-hash ETag, and a deploy never needs a cache purge because the edge caches each build under its own key. Deploying is three calls — POST a manifest of paths, sizes and SHA-256 hashes, PUT only the files the reply says are missing, then activate — and needs a write grant. Per-instance settings: SPA mode, clean URLs, the 404 path, and a maximum file size (25 MB by default, up to 100 MB); 5,000 files per deployment, and the most recent 10 deployments are kept. Billed on served requests (a cache hit included) and stored bytes deduplicated across builds. - MCP server: the console's own capabilities as tools for an AI agent, reached with a control-scoped API key or the OAuth connector. Rate-limited to 600 requests per minute per organization. Tool calls are metered; connecting, listing tools and reading resources are free. Work done through a tool bills to its own service as well, exactly as the same operation over REST would. ## Pricing One plan: pay-as-you-go. The first US$3.00 of usage each month is free for every organization; you pay only the amount above $3. Rates: Search queries $0.50 per 10,000 requests; Search reads $1.00 per million (one read = up to 100 rows examined; a selective query is a read or two, a cached repeat bills zero reads — just its query); Search writes $2.50 per million rows written (a document put writes its row plus its index rows); Search stored data $0.80 per GB-month (documents plus their index); Channel message deliveries $2.50 per million; Channel connection time $0.02 per million connection-seconds; Datastore writes $2.00 per million; Datastore reads $0.50 per million (one read = up to 100 rows examined, so a get or small page is 1 read and a large query/aggregate pays for the rows it scans); Datastore stored data $0.80 per GB-month; Auth sign-ups $0.10 per 1,000 accounts created; Auth sign-ins $0.10 per 10,000 issued token pairs (every successful sign-in and every token refresh); Auth stored users $0.01 per 1,000 users per month, where the account count is sampled hourly and averaged over the month (the same shape as stored data); Functions invocations $2.00 per million; Functions CPU time $0.10 per million CPU-milliseconds; Functions deployed functions $0.10 per function per month, prorated from the day you deploy it and charged whether or not the function is ever called; Blob stored files $0.04 per GB-month, sampled hourly and averaged over the month; Blob uploads $0.02 per 1,000 upload links used; Blob writes and lists $12.00 per million operations; Blob reads $1.00 per million operations, with a cached public read billing nothing and bandwidth not metered at all; Static requests $1.00 per million served requests, a cache hit included; Static stored files $0.04 per GB-month, deduplicated across builds and averaged over the month; Static uploads and deletes $12.00 per million operations, with bandwidth not metered at all; Containers machine time $0.02 per 1,000 machine-seconds, scaled by size so a second on a large counts as twelve on a small; Containers jobs $1.00 per 1,000 jobs started; Automation connected agents $5.00 per million agent-seconds (about $13 a month for an always-on machine); Automation runs $1.00 per 1,000 runs started; Automation run time $0.02 per 1,000 seconds a run spent executing; MCP tool calls $0.02 per 1,000. Automation prices no storage of its own — a run's files are blob objects and bill on Blob's stored-files line. There is no charge for idle capacity; the one standing charge is a deployed function. No tiers, seats, or minimums; no credit card required to start. ## Pages - [Home](https://altengine.net/): What altengine is — the platform overview, the four service groups (data & files, users & realtime, code, delivery & tooling), how they compose into an app with no backend of your own, and how it is priced. - [API documentation](https://altengine.net/docs): Base URL, authentication, grant levels, quickstart, and errors for the Search, Channel, Datastore, Auth, Functions, Blob, Containers and Automation APIs. - [Search API reference](https://altengine.net/docs/search): Documents, field types, the query language, facets, sorting, and pagination. - [Channel API reference](https://altengine.net/docs/channel): Subscriber tokens, HTTP and WebSocket publish, and WebSocket subscribe with live channel control. - [Datastore API reference](https://altengine.net/docs/datastore): JSON documents, string/number keys and auto-id, the query and aggregate language, indexes, transactions, and backups. - [Auth API reference](https://altengine.net/docs/auth): End-user accounts, the configurable sign-up form, the four sign-in methods, identity tokens and refresh, row-level access rules, and the embeddable sign-in form. - [Functions API reference](https://altengine.net/docs/functions): Sandboxed JavaScript on its own URL, capability-scoped clients for the other services, secrets with two exposures, the outbound allowlist, CORS, error groups and live tail, and local development. - [Blob API reference](https://altengine.net/docs/blob): Files uploaded straight to storage with a short-lived signed link, multipart uploads for anything past 5 GB, public files on a subdomain of their own with bandwidth that is not metered, the blobkey stored in a document to refer to one, and the job token a container reaches a store with instead of a key. - [Containers API reference](https://altengine.net/docs/containers): Run a Docker image as a background job for as long as the work takes — sizes, the completion callback, the blob store a job reaches with no credential of its own, why only an organization key can start one, and the per-instance limits on images, runtime, concurrency and cost. - [Automation API reference](https://altengine.net/docs/automation): Run your own scripts on your own Windows machines to drive desktop applications and firewalled portals — enrolling an agent, machines a machine enrols itself under a name that always means the same machine, exclusive vs parallel scripts, the three lanes a script can run in, the Windows installation media a machine builds a guest from, schedules fired by the machine's own clock and optionally fanned out one run per guest, the exceptions one machine may hold to a fleet schedule — changing its time, zone or parameters gives that machine a run of its own, while switching it off there leaves the fleet's single run shared — chained runs, the cost ceiling that replaces a wall clock, the per-run output directory an application's Save As dialog writes into, uploads that carry on in the background while the script does, waiting for an export to stop growing, streaming file and CSV reads that never hold a gigabyte in memory, running a program and reading its exit code, the two completion targets a finished run has — a function of yours invoked with its own grants, or a signed webhook — the debugging bundle a failed run leaves behind including the optional screen recording of the two minutes before it failed, the two permissions live desktop inspection requires, the same discovery loop served on the machine itself by `altengine-worker studio` — loopback only and with no sign-in, so anything on that machine that can open the port can drive its desktop — attended capture, where a person at the machine performs the task by hand and the recording keeps both the screen and the accessibility tree so selectors can be written from what the applications actually did, which will not start unless the agent can put a notice on the screen it is about to record and which adds no billing line of its own, the three lifecycle hooks a fleet runs on a machine — installed, updated, and about to be uninstalled, the last of which runs from the machine's own cached copy after the fleet has already removed it, and none of which stops an install or an uninstall by failing — what an agent's online state rests on — a machine that reported in within a published window, an older agent whose online is only a held socket, and a machine that keeps reconnecting instead of holding one socket, which reports in on every connection and is still rarely up long enough to be given work — and the three outcomes of delivering a value to a running job, the third being an unconfirmed delivery that answers 202 and must not be retried. - [Automation script API](https://altengine.net/docs/automation-script): The complete surface a script can call, as a reference — job (params, outDir, emit, chained runs, per-machine state, waitForData), env including writing a value back, sys.exec, sys.desktop() for whether there is a desktop to drive at all, streaming fs and csv, crypto, time in a real IANA zone because this runtime has no Intl, http.fetch, http.download and downloadAll streaming to disk with no size cap, a SQL Server, PostgreSQL and MySQL client whose reads stream a row at a time, whose named parameters make a stored procedure callable, and whose transactions are a scope rather than a begin/commit pair, PBKDF2 for reproducing an application's own login, raw TCP sockets, task.run and task.parallel on their own runtimes with no closures, the ui window and element surface, mouse, clipboard, OCR and template matching, a browser whose profile survives between runs, vm.* for the VirtualBox guests a machine hosts — including building one that does not exist yet and installing the hypervisor itself — artifacts, and the bounds that stop a run. - [Automation tips & recipes](https://altengine.net/docs/automation-recipes): The patterns, and the reasoning that does not belong in a reference — waiting on facts instead of sleeps, matching a window by class rather than by title, checking how many things a selector matched before trusting the first, hashing rows to extract only what changed, driving an application's Save As dialog and streaming the export it writes, fetching thousands of files at a bounded rate, giving a run a clean guest machine restored from a snapshot, reading a grid and picking from a list by name, falling back to OCR and template matching when there is no control tree, receiving a one-time code from another system, surviving a forced password change, keeping a browser login across runs, chaining long work into a run per unit, and debugging a machine that is switched off. - [Static API reference](https://altengine.net/docs/static): Deploying a built directory, the content-addressed upload that only sends what changed, deployments and the pointer move that publishes or rolls back one, how a path is resolved (directory indexes, the trailing-slash redirect, clean URLs, SPA mode, the 404 page), which filenames are cached for a year and why a deploy needs no purge, serving a directory locally, the three-call deploy API, and the per-instance settings. - [MCP server](https://altengine.net/docs/mcp): Connecting an AI agent with a control-scoped key or the OAuth connector, what each access level may do, the tools governance deliberately withholds, and the rate limit and per-call price. - [Pricing](https://altengine.net/pricing): The $3/month free tier and the usage-based rates for Search, Channel, Datastore, Auth, Functions, Blob, Containers, Automation and MCP. - [About](https://altengine.net/about): Why we're rebuilding App Engine's simple managed services and the principles behind the build. - [Blog](https://altengine.net/blog): Announcements, engineering notes, and migration guides. ## Posts - [A JSON Document Store That Doesn't Fight Your Schema](https://altengine.net/blog/json-document-store-that-fits-your-schema): altengine's Datastore API takes any JSON object, with no declared property types and no index file to maintain — and still keeps every query index-served, joined by key, and strongly consistent. Here is how it works and what it costs. - [Faceted Search, Explained (with a Working Example)](https://altengine.net/blog/faceted-search-explained-with-example): Facets are the counts next to a filter — 'Jackets (42)'. Here is what separates a facet from a filter, a real faceted query and response over the Search API, and what facets actually cost. - [How to Add Full-Text Search to Your App with a REST API](https://altengine.net/blog/add-full-text-search-to-your-app-rest-api): A hands-on walkthrough: create an index with one write, push structured documents, then run fielded queries with facets, sorting, snippets, and cursor pagination — all over plain HTTP. - [Managed WebSocket Pub/Sub Without Running a Server](https://altengine.net/blog/managed-websocket-pub-sub-without-a-server): Self-hosting realtime means owning connection state, a fan-out backplane, and every reconnect. Here is the managed shape instead: HTTP publish, one client WebSocket carrying many channels, channel-scoped tokens, and a bill that goes to zero when nobody is connected. - [The Cheapest Managed Full-Text Search for Small Apps](https://altengine.net/blog/cheapest-managed-full-text-search-small-apps): Most hosted search is priced for scale a small catalog doesn't have — either a rented cluster with a monthly floor or per-record fees that climb. Here's how the two models differ, and how to keep managed search at or near zero while you're small. - [Migrating App Engine Search to a REST API Without Rewriting Your Queries](https://altengine.net/blog/migrate-app-engine-search-to-rest-api): Moving off App Engine's Search API touches less than you think. Your query strings, field types, facets and document schemas carry over as-is — what you actually rewrite is the call layer that sends them. - [Replacing App Engine's Channel API for Realtime in 2026](https://altengine.net/blog/app-engine-channel-api-alternative-2026): App Engine's Channel API is gone. Here are the three real ways to get realtime pub/sub in 2026 — a self-hosted socket server, a large realtime platform, or altengine's Channel revival — with honest trade-offs and accurate request shapes. - [The App Engine Search API Is Gone: Your Real Options in 2026](https://altengine.net/blog/app-engine-search-api-alternative-2026): App Engine's Search API is retired. Here are the three honest replacement paths in 2026 — run your own cluster, adopt a big hosted search service, or use altengine's semantics-preserving revival — with the real trade-offs on cost, ops, and migration effort. - [What managed search really costs: altengine vs. Algolia, Elastic, and the rest](https://altengine.net/blog/what-managed-search-costs): Most hosted search either rents you a cluster with a monthly floor or bills per record until a catalog gets expensive. Here's how the options actually price out — and where altengine lands. - [Announcing altengine: App Engine's Search, Channel, and Datastore, semantics intact](https://altengine.net/blog/announcing-altengine): The Search and Channel APIs that App Engine retired are back, and its Datastore comes along as a standalone document store — three simple cloud services with a genuinely free tier. Here's what we built and why. ## Legal - [Terms of Service](https://altengine.net/terms) - [Privacy Policy](https://altengine.net/privacy) ## Getting started 1. Create an organization in the console at https://console.altengine.net 2. Generate an API key with a grant for Search, Channel, Datastore, or any combination. 3. Call the REST API with that key. Existing App Engine Search/Channel queries and document schemas carry over unchanged; what you write is the HTTP call layer. 4. For a client-only app, provision an Auth instance instead of shipping a key: configure its sign-up form and access rules, sign the end user in against /v1/auth/{instance}, and send the returned id_token straight to Datastore and Channel from the browser.