Start here

Nineveh turns an Aptos contract into a live database with a REST API. You describe the state you want, and it stays in sync with the chain — no indexer to run, no server to keep up.

This is the short version: what Nineveh does, the one idea everything rests on, and where to go next. It takes about five minutes.

Nineveh is alpha, and the hosted service isn't live yet. It works end to end — that's what the next page walks you through — but today you run it yourself, on your own Postgres. It takes about five minutes to get going: Running Nineveh yourself.

Everything on these pages applies either way. When the hosted service opens, the only thing that changes is who runs the process.

What you get

Point Nineveh at a contract address. It reads that contract's activity from the chain and folds it into tables you define. Those tables are served three ways:

  • a REST API over every table, with filtering, ordering and paging
  • a change feed that pushes every row change as it happens
  • webhooks, signed, to a URL of yours

You write two things: a short config naming the contract data you care about, and reducers saying what each record changes. Nineveh does the rest.

Why this exists

Aptos gives you point reads: one resource at one address, one view function, one table item by key. That is all the chain itself can answer.

It cannot answer how much volume did this market do today, or show me every open position, or what changed since I last looked. Those questions need the contract's history folded into shape, and on-chain storage costs gas, so contracts deliberately don't keep it. The shape of your app's data lives in events and resource changes — a stream of things that happened, not a table you can query.

Nineveh is the thing that turns that stream into tables.

The one idea

Everything else follows from this, so it's worth a minute:

chain  →  records  →  reducers  →  state tables  →  your app

The chain is the input. Records are what arrived — the events and resource writes your project follows. Reducers fold those records into state tables. Your app reads the tables.

Four things follow, and each one saves you a surprise later:

State is derived, not written. There is no POST /rows. Every row exists because a reducer put it there. If a number looks wrong, the reducer is wrong — nothing else can have touched it.

Reducers are deterministic. No clock, no randomness, no network calls. The same records always produce the same tables. That is what makes the next two possible.

Your records are kept. Change a reducer and Nineveh replays your own stored records — seconds — instead of re-reading the chain, which would be hours. Editing is cheap.

Aptos finalises. Committed transactions never reorg, so there is no rewind logic and no "wait for N confirmations". A version cursor is the whole safety story.

In order, if you're new:

  1. Your first backend — a working project against a live contract, end to end. Start here; everything else makes more sense after it.
  2. Reducers — how to say what your tables hold. This is the part you'll spend your time in.
  3. Reading your data — the REST API, the change feed, webhooks.
  4. Running a project — changing it, what a rebuild costs, limits, and what to do when something looks wrong.

Two references, for when you need a specific answer:

And the one you need today: Running Nineveh yourself covers building it, the CLI, the control plane, and what you take on as the operator.

What Nineveh is not

Worth knowing now, so you don't design around something that isn't there.

It is not a general backend. Your tables are a read-only projection of the chain. There are no writable app tables, no user accounts, no row-level security. If you need those, you need them somewhere else.

It does not do live aggregate queries. You can subscribe to a table or a row and be told when it changes. You cannot subscribe to "the top ten by volume" and have Nineveh keep the answer correct as trades arrive. Compute aggregates in your reducers instead, into a table, and subscribe to that.

It does not replace Aptos' own indexer for generic data. Token balances, NFTs and name lookups are already served by the hosted Indexer API. Nineveh is for state that is specific to your contract.

GraphQL isn't built. The config accepts graphql: true and does nothing with it. REST and the change feed are real.