Infrastructure

Solana Historical Data: RPC, Indexers, and SQL Access

Compare archival RPC, historical APIs, self-built indexers, and managed SQL-first indexers for Solana historical data, analytics, and production queries.

by Ilya Sekretarev·published 2026-07-28·14 min read
Solana Historical Data: RPC, Indexers, and SQL Access

Every analytics product that touches Solana runs into the same wall eventually: the data is technically available, and still not usable on its own. A backfill script can retrieve a large historical range. Making sense of it — grouping by wallet, joining against a launch, aggregating by hour — takes a different layer of work.

Solana historical data usually means one of two things: SOL price history, or the on-chain record — transactions, decoded swaps, token launches, liquidity migrations. This is about the second.

An archival RPC endpoint can return old transactions. A historical API can smooth over some of the pagination and filtering. Beyond that, analytics work still needs decoding, normalization, storage, schema maintenance, and a query layer that handles joins and aggregation across time.

RPC covers narrow lookups, archival access covers controlled backfills, and past that point the choice is really between owning an indexing stack or renting one — building it in-house when the data model is core infrastructure, or using a managed SQL-first indexer when decoded historical datasets are the dependency rather than the product.

What Counts as Historical Solana Data

Historical Solana data is easier to evaluate when it is split into three layers:

  • Raw chain and RPC records — blocks, transactions, signatures, instructions, logs, and execution metadata. Some of this lives directly in the ledger; logs and similar metadata come from how RPC surfaces transaction results. How much of any of it a given node can return still depends on that node's retention configuration, not just whether the request is valid.
  • Decoded events — swaps, token creations, pool migrations, and whatever else a given protocol emits that's worth naming. Someone still has to parse the raw instruction data and turn it into a schema with consistent field types.
  • Analytics-ready datasets — rows structured so they can be filtered, joined, grouped, and aggregated without reconstructing the transaction graph on every run.

A historical lookup can answer whether a record exists. Analytics needs records shaped so they can be compared, joined, and aggregated.

What Standard and Archival RPC Provide

Standard JSON-RPC is built for point lookups: get this transaction, get the current state of this account, get signatures for this address. It's a good tool when the application already knows what it's asking for and just needs the answer quickly.

Archival RPC extends that by keeping older ledger records reachable past normal node retention. Some products described as Solana historical data APIs primarily extend this same retrieval layer, sometimes with parsed endpoints, filtering, or pagination added on top. Underneath, it's still request-response access to individual records.

For a single known wallet, that may be enough: page through its signature history, fetch the relevant transactions, and inspect the records directly.

Why Archival Access Is Not an Analytics Layer

Archival access solves retrieval. Analytical workloads add a different set of requirements:

  • it gets old transactions and signatures back as individual records, without the joins or grouping a queryable dataset would need;
  • pagination and backfills work, but each backfill is its own job, run against a moving target;
  • there's no unified analytical schema across protocols — a swap on one DEX and a swap on another don't arrive shaped the same way;
  • protocol instructions still need decoding on the client side, instruction by instruction, program by program;
  • results still need somewhere to live — archival RPC returns data on request; storing it for later queries is left entirely to the client;
  • searching for events without known addresses or signatures is a poor fit for request-response retrieval, since the interface is built around "give me records for X," not "find records matching this pattern";
  • and if decoder logic changes, or a bug gets fixed in how a field was parsed, that reprocessing has to run against everything already pulled, not just new data going forward.

The result is that most non-trivial historical questions on Solana still require a decoding and storage layer somewhere in the stack, whether that's built in-house or provided by a vendor.

The Five Layers Between RPC and SQL

Diagram showing how raw Solana RPC transaction data becomes queryable analytics through normalized fields, decoded protocol events, optional enrichment, ClickHouse tables, and SQL results.

From raw RPC data to queryable Solana analytics.

A single swap moving from a raw transaction to a number in a dashboard passes through several distinct steps.

  1. Raw records — an RPC transaction: a signature, a list of instructions, the raw account keys involved. This is what getTransaction hands back.
  2. Normalized records — the specific instruction gets isolated, and its accounts and data get pulled into typed fields: a wallet, a mint, an amount, still tied to the exact protocol version that produced them.
  3. Decoded protocol events — those fields become a named row: a swap, with a direction, a wallet, a token pair, a timestamp. This is the point where "instruction number 3 in this transaction" becomes "a buy."
  4. Enriched records — optionally, context gets attached: a USD price at the time of the trade, a label, a protocol-specific flag. Not every dataset needs this layer.
  5. Analytical aggregates — hourly volume, a wallet's trade count over a week, a cohort of early buyers. Once records reach this point, these become SQL queries against decoded tables, not a separate data-engineering project.

RPC gets you to raw retrieval. A managed indexer packages the downstream work: normalization, decoding, analytical storage, and a query surface where aggregates can be computed without rebuilding the transaction model in application code.

Where RPC-Based Analysis Becomes an Indexing Project

Once historical pulls reach any real volume, a predictable list of work shows up — the work that turns a one-off script into a maintained data pipeline:

  1. pagination and rate-limit handling across a growing request count;
  2. incremental synchronization, so history doesn't get re-pulled on every run;
  3. decoding instructions and CPIs (cross-program invocations) for each protocol version in scope;
  4. normalizing amounts, mint addresses, and protocol-specific wallet and account-format differences;
  5. deduplication and basic data-quality checks;
  6. storage design: indexing, partitioning, and figuring out how long anything needs to be kept;
  7. monitoring and recovery when a node falls behind or a decoder breaks after a protocol upgrade.

Protocol upgrades are the part that often changes the maintenance profile. A decoder that worked fine in March can start dropping fields in June because a program upgraded and changed the instruction shape. Schemas evolve, duplicate or malformed records need handling, and historical records sometimes need reprocessing after a decoder gets fixed — otherwise the same field means something slightly different depending on which month of data you're looking at. This applies to any indexing layer, self-built or managed. It's part of what the work is, not a one-time setup cost.

How a Managed Indexer Works

At the infrastructure level, the pipeline is straightforward:

Solana RPC → ingestion → normalization → protocol decoders → optional enrichment → ClickHouse → SQL

The raw records still have to come from the chain. What a managed indexer packages is everything downstream of it — normalization, decoding, storage, and a query surface that stays stable enough for repeated production queries. Real-time streaming and historical indexing solve different parts of the data stack, and it's worth keeping that distinction in mind rather than treating them as competing approaches to the same problem.

The useful distinction is not access alone, but structure: stable decoded tables, consistent field types, and relationships that can be queried repeatedly.

RPC vs Archival API vs Self-Built vs Managed Indexer

ApproachBest forData formEngineering burdenMain limitation
Standard RPCPoint lookups, live application readsRaw per-request responsesLow, for narrow tasksPoor fit for broad historical analytics
Archival RPC / historical APIWallet history, controlled backfillsRaw or lightly parsed responsesMediumModeling, storage, and reprocessing still sit with the client
Self-built indexerFull control, proprietary data modelFully customizableVery high, ongoingContinuous decoder and infra maintenance
Managed SQL-first indexerProduction analytics on decoded datasetsQueryable database tablesLow internallyCoverage limited to indexed protocols

The right choice depends on the workload. A team debugging one wallet's history for a support ticket is better served by a quick lookup than a warehouse. A research team running weekly cohort analysis across multiple indexed protocols will usually want decoded tables before it commits to maintaining its own decoders.

Where SQL Access Changes the Workload

Once a question involves joins, time windows, or repeated aggregation, direct SQL access over a decoded warehouse starts saving real time — mostly because the same relationships stop needing to be rebuilt on every run.

Take a fairly ordinary research question: which wallets bought a token within five minutes of its creation, over the last week, on a specific launch protocol. Through RPC, that means pulling every relevant transaction, decoding it client-side, matching timestamps, and joining creation events to swap events in application code. Over ClickHouse, with decoded tables already in place, it looks closer to this:


SELECT

   s.signing_wallet,

   count(*) AS early_buys,

   sum(s.quote_coin_amount) / 1e9 AS sol_spent

FROM pumpfun_all_swaps s

INNER JOIN pumpfun_token_creation c ON s.base_coin = c.mint

WHERE s.direction = 'buy'

 AND s.block_time BETWEEN c.block_time AND c.block_time + INTERVAL 5 MINUTE

 AND c.block_time > now() - INTERVAL 7 DAY

GROUP BY s.signing_wallet

ORDER BY early_buys DESC

LIMIT 50

A simpler aggregation, such as hourly Raydium volume over the last day, shows the same difference:


SELECT

   toStartOfHour(block_time) AS hour,

   count(*) AS swaps,

   sum(quote_coin_amount) / 1e9 AS sol_volume

FROM raydium_all_swaps

WHERE block_time > now() - INTERVAL 24 HOUR

GROUP BY hour

ORDER BY hour

The queries stay intentionally ordinary. What's different is that the decoding and table relationships already exist, so nobody rebuilds them for every analysis.

SQL and APIs serve different access patterns. An API is useful when the query shape is known and stable: this wallet's trades, this token's stats, this account's activity. SQL is better when the question keeps changing, as it usually does in research and analytics. A production application can sit an API in front of a SQL warehouse just fine, but having an API doesn't replace the underlying data model — it just decides how much of that model gets exposed, and how flexibly.

Data Freshness and Coverage

Historical depth and freshness are different characteristics. A dataset can go back years and still update slowly, or it can be nearly real-time and only cover the last few months. Both are legitimate designs; they just serve different questions.

Supanode currently describes its data freshness as approximately 15 seconds behind the chain — that's analytics latency, distinct from execution latency or a formal SLA. Split-second trading decisions call for a different layer: streaming infrastructure built specifically for execution.

Coverage should be checked at the table level. "Historical since January 2024" is a reasonable headline, but it rarely means every dataset behind it starts on the same date or gets retained for the same length of time. Some tables reach back further than others; some get pruned after a matter of weeks, while others are retained for substantially longer periods. The reliable way to know is to check the specific dataset against the specific date range a workload needs.

What Supanode Currently Provides

Supanode fits the managed SQL-first indexer category, but the product boundaries matter. It operates as a managed, customizable Solana data warehouse: direct ClickHouse SQL access to a defined set of decoded historical and near-real-time datasets, in place of a fixed REST endpoint with a handful of hardcoded parameters.

The documented coverage is organized around several dataset families: Pump.fun activity (token creation, swaps, fee distributions), Raydium activity (swaps and launchpad migrations), Meteora swap and dynamic-bonding data, Jito tip records, plus a set of block and timestamp tables that support the rest.

Ingestion runs through RPC rather than a proprietary validator feed. Coverage and retention vary by table, so the practical move is checking the current table reference for the exact dataset and window a workload needs, rather than leaning on one headline claim.

Standard Access vs Custom Indexer Work

The standard product and custom engineering work should be separated clearly.

The core service is the published warehouse: existing indexed datasets, direct ClickHouse SQL access, near-real-time updates, and historical depth limited by each table's documented coverage start date and retention window. That is the baseline product.

Decoding a protocol that is not already in the table reference, running an isolated instance, or wrapping the warehouse in a custom API sits outside that baseline. These are buildable, but they should be scoped as custom engineering work rather than assumed as part of standard access.

Three Practical Workload Examples

Token launch research. The event chain needed is fairly specific: token creation, swap history right after it, precise timestamps, signing wallets, and migration events from bonding curve to AMM. Through RPC, reconstructing that sequence means fetching creation transactions, then separately paging through swap activity, then manually aligning timestamps across both. With decoded SQL tables, the same question becomes a join over creation and swap events with a time-window filter.

Wallet cohort analysis. This one needs activity across many wallets at once, joins across tokens and protocols, and aggregation repeated over shifting historical windows — this week, last week, the week before a specific event. RPC handles "what did this one wallet do" well. It doesn't handle "which two hundred wallets behaved this way across four protocols" without a significant amount of client-side bookkeeping.

Production analytics backend. Here the requirement shifts from one-off research to something that needs to keep working: a stable schema, predictable query patterns, reusable tables that don't need re-validating every time someone queries them. Whether that sits behind a dashboard or an internal service, it usually benefits from a defined SQL layer underneath, with a custom API or dedicated indexer added only if the workload eventually needs one.

When Building Your Own Indexer Makes Sense

Self-building is the right call when the data model itself is the product — when ingestion, decoding logic, and normalization are the actual intellectual property, not commodity plumbing underneath something else. It's a reasonable choice, but it's worth being clear-eyed about what it actually means to own, on an ongoing basis:

  • ingestion from RPC or another source, kept running continuously;
  • retries and recovery when nodes lag or fail;
  • storage, at whatever scale the workload grows into;
  • ClickHouse (or equivalent) tuning as query patterns change;
  • protocol decoders, maintained through every upgrade;
  • schema migrations as fields and protocols evolve;
  • monitoring, so ingestion or decoder failures are caught before they affect downstream queries;
  • historical reprocessing when a decoder bug gets fixed;
  • access control for users and services querying the data;
  • query performance, as tables and usage both grow;
  • developer documentation, so the schema doesn't live only in one engineer's head.

That is the actual scope behind "build an indexer." It can be the right decision, especially when the data model is part of the product. But it is an ongoing operating commitment, not a one-time implementation task.

How to Evaluate Historical Data Coverage

Before choosing a data layer, test it against the exact workload:

  1. Define the exact event needed — not "Solana swaps" broadly, but the specific protocol and event type.
  2. Check whether that event is already decoded, or would need to be built.
  3. Check the first available record for that specific table, not the product's headline coverage date.
  4. Check retention — how long the data actually stays queryable.
  5. Check the required fields against what's actually exposed, not just the table name.
  6. Test the actual query the workload needs, against real data, before assuming it'll work.
  7. Confirm freshness requirements — whether the workload needs seconds-level delay or can tolerate more.

This usually surfaces mismatches faster than evaluating the product at the headline level.

Conclusion

Retrieval and analysis are different problems. Archival RPC can solve the first one. The second requires decoding, normalization, storage, schema maintenance, and repeatable querying across protocol changes.

The right choice depends on ownership. Build the layer internally when the data model is core infrastructure or product IP. Use a managed indexer when the product needs decoded datasets and SQL access without operating the full ingestion and decoder pipeline.

Before building on top of any dataset, check current tables, start dates, retention, fields, and freshness against the exact queries the product needs.

Written by Ilya Sekretarev
Infra operators since 2023 · questions → @supanode_tgs
.RELATED ARTICLES// hand-picked by the author