StondelBook a call
← All notes
Fullstack Web3 architecture

What “fullstack” actually means when there is a chain underneath

A contract is not a product. A smart contract replaces one slice of a backend — the settlement layer — and the gap between a deployed contract and something a person can use is mostly ordinary software engineering.

Indexing pipelines · transaction lifecycle · RPC resilience · data topology

Stondel12 min read465 views

Executive summary

In traditional web development a backend database handles reads, writes, business logic and authorisation inside a controlled, private environment. In a decentralised application the smart contract replaces only a small fraction of that stack: the execution layer for financial and consensus-critical state.

Because blockchains are deliberately slow, public, and optimised for verification rather than query performance, a fullstack Web3 application needs an extensive conventional infrastructure layer to make on-chain state usable, responsive and resilient.

The read path: indexing and aggregation

Reading state directly from an EVM RPC node does not scale to a modern interface. Nodes are optimised for block consensus, not relational queries.

Where direct RPC runs out

  • No complex filtering — you cannot natively ask for "every ERC-721 owned by user X, minted in the last 30 days, with attribute Y".
  • Rate limits and cost — querying historical logs across thousands of blocks through a public or paid endpoint means throttling, a runaway bill, or both.
  • Latency — node responses take hundreds of milliseconds each, and a page needing dozens of state checks compounds that into something users feel.

What you have to build instead

  1. Event ingestion — block listeners stream on-chain logs and state updates into a queue such as Kafka or BullMQ.
  2. Transform and store — a processing service decodes ABIs, parses raw log data and writes relational records into Postgres, ClickHouse or a GraphQL graph.
  3. Caching — Redis absorbs high-frequency reads such as balances and metadata, keeping client load times under 100ms.

The write path: transaction lifecycle management

Writing to a chain is asynchronous, non-deterministic, and can fail at several independent points. The interface has to model every stage explicitly rather than treating submission as success.

  • Mempool stalls — a transaction with a low gas fee can sit indefinitely. The app needs speed-up (resubmit at a higher fee with the same nonce) and cancellation paths.
  • Replaced transactions — when a user speeds up or cancels in their wallet, the original hash becomes invalid. Track nonces, not just hashes.
  • Reorgs — a block containing a confirmed transaction can be discarded several blocks deep. Financial actions need a confirmation threshold before off-chain state moves.
  • Optimistic updates — rather than making users wait twelve seconds, apply state locally and keep the rollback path for when it drops.

The client edge: wallet and chain reality

The Web3 client runs in an unusually unstable environment. The wallet is an external extension or mobile app over which you have no control, and every one of its failure modes surfaces in your interface.

Edge caseConsequenceMitigation
Wrong networkContract calls fail silently or revertDetect chain ID on init; prompt a switch via wallet_switchEthereumChain
RPC outageThe app stops fetching on-chain data entirelyClient-side fallback providers with round-robin retry
Insufficient gasThe transaction fails before the user even signsSimulate with eth_estimateGas before prompting, and warn early
User rejectionAn unhandled promise rejection breaks the flowIntercept code 4001 explicitly and reset local state quietly

Data topology: what actually belongs on-chain

Putting everything on-chain is prohibitively expensive and creates real privacy problems. The architecture needs an explicit rule for where each class of data lives.

Decoupling with EIP-712 signatures

To cut gas and transaction fatigue, modern architectures push as much as possible into off-chain cryptographic signatures:

  1. Users sign structured, human-readable messages off-chain, for zero gas.
  2. The application stores those signatures off-chain — order books, gasless approvals.
  3. Signatures settle on-chain in bulk, or lazily, only when settlement is genuinely required.

Conclusion

A smart contract is a secure settlement engine, not a product.

Building a working dApp means wrapping that settlement engine in ordinary software engineering: query indexing, asynchronous event processing, resilient RPC orchestration and defensive interface design. Skip those layers and you ship a working protocol nobody can actually use.