Skip to main content
This quickstart takes you from nothing to live onchain data in your own database in about ten minutes. You generate a sink starter pack in the Admin Panel, run it with Docker, and query your first rows. Every recipe and migration guide then follows the same pattern.

Before you begin

Data Feeds is a technical product: you run the infrastructure. Unlike the REST API, the data lands in a database you own and operate: you run the Docker sink, you provision Postgres/ClickHouse (locally for this quickstart; on your own servers in production), and you are responsible for storing, sizing, and backing up the decompressed data. Decoded onchain data expands significantly from its compressed transport size, so budget disk accordingly.
  • Docker and Docker Compose installed and running.
  • A Data Feeds API key (cm_live_...). Request access if you do not have one.
  • Access to the Moralis Admin Panel, where you generate the sink config.
  • A machine with enough disk headroom for your backfill window: start small (tip-500) and widen once you’ve seen the per-block footprint for your chain.

Step 1: generate your sink starter pack

In the Admin Panel, configure a sink (pick your chain, topic, and destination database) and download the starter pack (continuum-sink-starter.zip). Unzip it. You get:
FileWhat it is
sink-config.yamlThe sink config you generated: Continuum URL, namespace (chain), topic, and destination.
docker-compose.ymlBrings up the sink (moralisweb3/continuum-sink) plus a local PostgreSQL.
.envYour API key and DB password. Do not commit or share it.
schema.sqlDDL for the destination table(s), auto-applied to Postgres on first start.
README.txtThe same steps you are reading here.
namespace is the chain, as a hex chain ID. For example 0x1 is Ethereum, 0xa4b1 is Arbitrum One. See the chain reference below. topic (e.g. master-3) is the master block stream the sink reads.

Step 2: add your API key

Open .env and confirm your key is set; the generated file sometimes ships with a blank or placeholder key:
Keep your key private. It is a live credential. Never commit .env or paste the key into shared docs or chat. If a key leaks, rotate it.

Step 3: start the stack

From the unzipped directory:
This starts PostgreSQL (with schema.sql applied) and the sink. The sink reads a backfill window from the upstream S3 store, then tails live blocks. Watch it work:
Querying from your own app on the host? The bundled Postgres is only reachable inside the Docker network by default. Add a port mapping to the postgres service so you can connect from your machine:
Then connect to localhost:5544 (user/db sdf, password from .env).

Step 4: query your first rows

The default tokenTransfers config writes to a table named after your sink (here, sdf):
You should see the count climb as new blocks land. That is live, decoded onchain data in a store you own: no API quotas, no per-call limits.

If no rows arrive

The pipe has a few moving parts. Work down this list:
SymptomCauseFix
continuum.api_key is required in sink logsMORALIS_API_KEY blank in .envPaste your full cm_live_... key, docker compose up -d --force-recreate sink.
Sink logs stop after s3-proxy reachable and rows stay at 0Upstream S3 backfill stalled (e.g. “Partition not found”)Not your setup. Confirm the chain/topic backfill is healthy with the team, then it resumes automatically.
Can connect but app can’t reach PostgresNo host port mappingAdd the ports block from Step 3.

Chain reference

namespace in sink-config.yaml is the chain’s ID in hex:
ChainChain IDnamespace
Ethereum10x1
Optimism100xa
BNB Chain560x38
Polygon1370x89
Base84530x2105
Arbitrum One421610xa4b1
Avalanche431140xa86a

What just happened

  • The starter pack carried a generated sink-config.yaml (chain, topic, destination) and a matching schema.
  • The sink (moralisweb3/continuum-sink) read the master block stream, backfilled history, then stayed live.
  • You queried a normal SQL table, yours to join and shape freely.

Next steps