blockchainsv
Web3 Integration & APIs·July 15, 2026·15 min read

Web3 development services: what do they actually cover?

The awkward part of shipping a dApp is rarely the contract compile step. It is the moment the frontend says “transaction pending” forever, the RPC provider starts returning rate-limit errors during a…

Web3 development services: what do they actually cover?

The awkward part of shipping a dApp is rarely the contract compile step. It is the moment the frontend says “transaction pending” forever, the RPC provider starts returning rate-limit errors during a campaign, the wallet modal drops a user on the wrong chain, and the dashboard needs data that is technically on-chain but painfully expensive to fetch one call at a time.

That is where web3 development services become more than “write me a Solidity contract.” In production, the work stretches across wallet onboarding, frontend state sync, indexing, node infrastructure, oracle connectivity, decentralized hosting, and a lot of small UX decisions that decide whether a user completes the journey or quietly closes the tab.

Beyond smart contracts: the real scope of Web3 integration

When teams ask for dapp development services, they often start with a contract-shaped request: ERC-20 staking, NFT minting, escrow, governance, vaults, marketplace logic. Fair enough. The contract is the settlement layer. But the product the user touches is not the contract. It is the path from “connect wallet” to “I understand what happened and I trust the app enough to continue.”

A serious Web3 build usually has several layers moving together:

  • Smart contracts and protocol logic: Solidity or another contract language, tests, deployment scripts, upgrade strategy if the system uses proxies, event design, and security review.
  • Frontend wallet integration: wallet connection, chain switching, account state, disconnect handling, mobile wallet flows, and transaction lifecycle UI.
  • Contract reads and writes: typed ABIs, simulation before writes, gas estimation, confirmations, reverted transaction messaging, and graceful degradation when RPC calls fail.
  • Blockchain data querying: deciding what to read directly from nodes and what belongs in an indexer such as The Graph.
  • Web3 API integration: node providers, rate-limit management, API keys, fallback endpoints, telemetry, and caching.
  • Oracle and off-chain data paths: Chainlink price feeds, Chainlink Functions, custom API calls, or backend relayers where appropriate.
  • Storage and hosting: decentralized frontend hosting, metadata storage, pinned assets, content-addressed URLs, and migration planning when providers change.
  • Operational support: monitoring, alerting, incident response, and versioned deployment flows across testnets and mainnet.

This is why blockchain development outsourcing can go wrong when the scope is framed too narrowly. A vendor can deliver a contract that passes tests and still leave the team with a brittle app. The contract may be fine. The user journey is not.

Let’s make that concrete. Suppose we are building a lending dashboard. The contract exposes positions, collateral ratios, liquidation thresholds, and events. Reading all of that directly from an RPC endpoint on every page load might work for five beta users. It will not feel good once the dashboard has charts, filters, historical activity, and several wallets refreshing state at the same time.

A better architecture separates concerns. The contract remains the source of truth. The frontend uses direct reads for fresh, user-specific state where latency matters. Historical or aggregate data goes through an indexer. Transaction writes are simulated before submission. The UI treats each transaction as a state machine: idle, preparing, awaiting wallet, submitted, confirming, indexed, settled. That last step — indexed — is where many teams get bitten. A transaction can be confirmed on-chain while the UI still waits for the subgraph or database to catch up. If we do not model that lag, users see contradictions.

The contract may be the source of truth, but the frontend is where truth has to become legible.

Good web3 integration solutions handle those seams deliberately. They do not pretend the chain, the wallet, the indexer, and the UI all update in the same breath.

Optimizing frontend performance with Viem and Wagmi

Frontend performance is not vanity in Web3. Wallet modals, cryptographic libraries, ABI-heavy clients, and analytics scripts can turn a landing page into a slow handshake before the user even sees the first call to action. If the app targets mobile wallets, the margin gets thinner.

This is why the modern React Web3 stack has been moving toward viem and wagmi v2 for many EVM applications.

Viem is a lightweight, TypeScript-first alternative to ethers.js and web3.js. One practical reason teams consider it is bundle size: viem is around 35kB, while ethers.js v6 is around 200kB. That does not mean every ethers app must be rewritten tomorrow. Ethers remains mature and widely understood. But on a frontend where every kilobyte competes with wallet SDKs and app code, that difference matters.

The deeper difference is style. Ethers.js leans into object-oriented abstractions: providers, signers, contract instances. Viem uses a more stateless, function-driven Actions pattern. They are not drop-in interchangeable without code changes, and pretending they are is a good way to create a migration week nobody enjoys.

A practical comparison looks like this:

ParameterEthers.js v6Viem + Wagmi v2
Mental modelProvider/signer/contract objectsClients and typed actions
Frontend bundle pressureLarger, around ~200kBSmaller, around 35kB for viem
React integrationUsually custom hooks or third-party wrappersWagmi hooks built on viem
TypeScript ergonomicsGood, familiar to many teamsStrong ABI-driven typing and inference
Request cachingUsually app-managedWagmi v2 uses TanStack Query patterns
Migration effortOften lower for legacy dAppsHigher if coming from ethers abstractions

Wagmi v2 sits on top of viem and gives React teams reactive primitives for wallet connection, reads, writes, and transaction state. Under the hood, it uses TanStack Query, which is helpful because Web3 frontends are request-heavy in ways that look familiar to Web2 engineers: caching, invalidation, refetching, stale data, retry behavior.

This is one of those places where we should not throw Web2 patterns out the window. They are not obsolete. They are how we stop the interface from hammering an RPC endpoint every time a component re-renders.

A typical production pattern with wagmi might involve:

1. Separate public reads from wallet-dependent reads. Token metadata, pool parameters, and global protocol values do not need a connected wallet. Load them before the user connects.

2. Use prepared or simulated writes where possible. If a transaction will revert, we want to catch it before the wallet opens, not after the user signs.

3. Model transaction state beyond hash. A hash is not completion. We still need confirmation, possible replacement, indexer sync, and UI invalidation.

4. Invalidate precise queries after settlement. Do not refetch the whole app because one allowance changed. That creates friction and burns provider quota.

5. Design for chain mismatch from the start. “Wrong network” should be a recoverable UI state, not a dead end.

The nice thing about this stack is that it encourages us to treat Web3 state as reactive application state, not magical chain dust sprinkled over React components. That is healthier for teams and much kinder to users.

Wallet connection is product work, not a modal choice

RainbowKit, ConnectKit, and AppKit — formerly Web3Modal — all integrate with WalletConnect and wagmi in different ways. Choosing between them is not just a design preference. It changes the onboarding path.

If our user base is mostly crypto-native desktop users, a rich injected-wallet flow may be fine. If we expect mobile users arriving from social links, deep linking and WalletConnect behavior become central. If we serve enterprise users, we may need clearer network labels, safer account switching, and more deliberate copy around signatures.

The common mistake is treating wallet connection as a gate. “Connect first, then we show you the app.” Sometimes that is necessary. Often it is unnecessary friction. Let anonymous users browse public protocol data. Let them understand the offer. Ask for the wallet at the moment it becomes useful.

That one decision can improve the user journey more than any clever animation in the connect modal.

Data indexing and oracle connectivity for decentralized apps

The chain is excellent at finality. It is not excellent at answering every UI question quickly.

If a frontend needs “show me all positions opened by this address over the last six months, grouped by market, with status and realized PnL,” direct contract reads are the wrong tool. We can brute-force logs, paginate RPC calls, or maintain our own backend. But for many dApps, The Graph is the cleaner path.

The Graph organizes blockchain data using subgraphs. Developers define the events and entities they care about, then query that indexed data through a GraphQL API. This turns raw blockchain history into frontend-ready shapes: users, positions, orders, claims, votes, transfers.

A good subgraph is not just a mirror of contract events. It is an interface between protocol design and product experience. If the UI needs a portfolio screen, the subgraph schema should support that journey. If the analytics page needs daily aggregates, model aggregates instead of forcing the browser to calculate everything on load.

There is a subtle product issue here: indexed data lags behind chain confirmations. Usually the delay is small. Under load or during indexing issues, it can be noticeable. So we should design a state sync strategy:

  • After a transaction confirms, optimistically update local UI state where safe.
  • Show “syncing latest activity” instead of implying failure when the subgraph has not caught up.
  • Use direct contract reads for critical post-transaction values when freshness matters.
  • Reconcile indexed data once the subgraph reflects the event.
  • Track indexing delays in monitoring, not only in user complaints.
If our UI treats every backend as instantly consistent, the first real mainnet spike will teach the lesson for us.

Oracles introduce a different boundary. Smart contracts cannot fetch arbitrary web APIs on their own. They need an external mechanism to bring off-chain data or computation into the on-chain environment.

Chainlink Functions is one option for that class of problem. It allows smart contracts to request off-chain computation and API calls from a Decentralized Oracle Network by executing custom JavaScript code. That can be useful when a contract needs data that is not already available as a standard price feed: scores, attestations, external market data, or API-derived values.

But oracle design needs restraint. Not every API belongs on-chain. Some data is better handled by the frontend. Some belongs in a backend service. Some should be attested, signed, or periodically committed. The key question is: does the smart contract need this data to enforce value-moving logic, or does the interface need it to explain context?

For example:

NeedBetter fitWhy
Displaying token logos and descriptionsFrontend/API/indexerNot consensus-critical
Enforcing collateral valueOracle feed or verified oracle pathAffects funds directly
Showing historical user activityThe Graph subgraphQuery-heavy, event-derived
Fetching external eligibility data for a claimChainlink Functions or signed attestationContract may need verifiable result
Showing fiat estimates in UIFrontend data provider plus fallbackUseful context, not always settlement logic

This is where web3 development services should bring architectural judgment, not only implementation hands. Every off-chain dependency changes the trust model. Every indexing layer changes the consistency model. Every API key changes the operational model. None of that is scary if we name it early.

RPC providers are invisible until they are not. Then they become the whole incident.

During early development, a free endpoint feels endless. The app loads. Contract reads work. Transactions submit. Then a mint opens, a token list page refreshes too often, or a dashboard gets embedded in a partner site, and suddenly the provider starts pushing back.

Major node providers such as Alchemy and QuickNode offer free tiers, but those tiers are shaped differently. Alchemy’s free tier includes up to 300 million compute units per month. QuickNode’s free tier provides 10 million API credits and a rate limit of 25 requests per second. Those are useful numbers, but they are not interchangeable because providers weight requests differently. A heavy log query is not the same as a basic block number request.

So when we design web3 API integration, we should think in budgets, not just endpoints.

A production-minded RPC plan usually includes:

1. Request inventory. List what the frontend calls on initial load, wallet connect, network switch, transaction submit, and dashboard refresh.

2. Call weight awareness. Some methods are cheap; others are expensive. Event logs, traces, and archive reads can burn quota fast.

3. Caching at the right layer. TanStack Query in the client helps. So can server-side caching for public reads, depending on the app’s architecture.

4. Fallback providers. One provider outage should degrade the app, not erase it. Fallbacks need testing, not just configuration.

5. Rate-limit UX. If data cannot refresh, say that. Do not let spinners cosplay as progress.

6. Separate environments. Development, staging, and production should not all fight over the same provider key.

7. Telemetry. Track request volume, error rates, latency, and method distribution before a launch, not after Discord fills with screenshots.

The frontend can also reduce pressure by being less chatty. Multicall patterns help when many contract reads target the same chain. Query invalidation should be specific. Polling intervals should match the user need. A price display may need frequent updates. A governance proposal title does not.

And then there is SSR. Server-rendered or statically generated pages can improve perceived performance for public content, but they can also centralize RPC traffic through your infrastructure. That is not bad; it is just a different bottleneck. If every visitor triggers a server-side chain read, the bill and rate limits move from the browser to the server.

The healthiest approach is boring in the best way: know what is called, know how often, know what happens when it fails.

Modernizing decentralized storage after hosting changes

Decentralized hosting is another area where “set and forget” tends to age badly.

For years, teams treated IPFS hosting and pinning as a deployment checkbox. Upload frontend assets, pin metadata, put the hash somewhere, move on. But providers change. Products sunset. Operational ownership matters.

One concrete example: Fleek officially discontinued its legacy IPFS hosting service on January 31, 2026, which pushed developers to migrate pinned IPFS content to alternatives such as Filebase or Pinner. The lesson is not “never use Fleek” or “never use managed services.” The lesson is that decentralized storage still needs an exit plan.

For NFT metadata, frontend assets, and protocol documentation, we should know:

  • Who controls the account that pins or hosts the content.
  • Whether content hashes are recorded somewhere durable.
  • How gateways are selected and whether the app has fallbacks.
  • What happens if a hosting provider changes terms or shuts down a product.
  • Whether metadata is immutable by design or intentionally updatable.
  • How releases are versioned so users can verify what frontend they are using.

This matters because decentralized frontend hosting has two overlapping promises. One is resilience: the app should not depend entirely on a single server. The other is integrity: users should be able to know which code they are loading. Managed platforms can help, but they do not remove the need for release discipline.

There is also a UX angle. Raw IPFS URLs and slow gateways can be rough for mainstream users. A good deployment strategy might combine content-addressed storage, custom domains, gateway fallbacks, and clear release notes. Again, graceful degradation is the goal. If one gateway is slow, the app should not feel broken. If metadata is temporarily unavailable, the UI should present a recoverable state.

This is part of Web3 development work even though it does not look like smart contract engineering. It affects trust directly.

What a production-grade Web3 service engagement should deliver

If we are evaluating web3 development services, the useful question is not “can this team write Solidity?” It is “can this team carry a feature from contract logic to a reliable user journey?”

A strong engagement usually leaves behind artifacts and systems the internal team can keep operating:

AreaWhat we should expect
Contract layerTested contracts, deployment scripts, ABI management, event design, upgrade notes
Frontend integrationWallet flows, typed reads/writes, transaction state handling, chain switching
Data layerSubgraph or indexing plan, query design, consistency strategy
API infrastructureProvider selection, rate-limit plan, fallback endpoints, monitoring
Oracle designClear trust model, whether data belongs on-chain, integration tests
Storage and hostingPinning/hosting plan, gateway fallbacks, release process
DocumentationRunbooks, environment setup, known failure modes, handoff notes

The handoff matters. A beautiful codebase with no runbook is still fragile. The next engineer needs to know why a subgraph entity is shaped a certain way, why a provider fallback exists, why a transaction waits for two confirmations in one place and one confirmation in another.

We should also be honest about trade-offs. Not every project needs a subgraph on day one. Not every app needs Chainlink Functions. Not every frontend needs to migrate from ethers to viem immediately. Architecture should match the product stage.

For an MVP, the right answer may be direct reads, wagmi hooks, one reliable RPC provider, and careful UI state. For a protocol with analytics, rewards, referrals, and governance, indexing becomes much harder to avoid. For an app with value-moving external data, oracle design deserves serious time before code is written.

That is the practical center of Web3 integration: choosing where complexity belongs.

The bottom line: Web3 services are integration services

The best Web3 teams I have worked with do not treat the blockchain as a backend replacement. They treat it as one part of a distributed system with unusual guarantees and very visible failure modes.

A user does not care that our contract emits the perfect event if the activity page never updates. They do not care that our RPC architecture is elegant if the mint button times out. They do not care that our metadata is on IPFS if the image does not load and there is no fallback. Fair enough. Users judge the journey.

So when we say web3 development services, we should mean the whole path: contracts, wallets, reads and writes, indexing, oracles, node providers, decentralized storage, monitoring, and the small UX decisions that make unreliable networks feel manageable.

Let’s build with that in mind. Not heavier than needed, not thinner than production deserves. Just enough architecture to keep the user moving, even when the chain, the wallet, and the API provider all decide to make our afternoon interesting.

FAQ

Why is it better to use an indexer like The Graph instead of direct contract reads?
Direct contract reads are inefficient for complex queries, such as historical activity or aggregated data. An indexer organizes blockchain data into queryable shapes, preventing performance issues as the dashboard grows.
What is the main difference between ethers.js and viem for Web3 development?
Viem is a lightweight, function-driven library focused on TypeScript and smaller bundle sizes (around 35kB), whereas ethers.js uses an object-oriented abstraction and has a larger footprint (around 200kB).
How should a dApp handle transaction state to improve user experience?
The UI should treat transactions as a state machine—tracking them through stages like idle, preparing, awaiting wallet, submitted, confirming, and indexed—to avoid showing contradictory information.
What should be considered when choosing an RPC provider?
Developers should evaluate providers based on call weight, rate limits, and request inventory. It is essential to implement fallback providers and telemetry to ensure the app remains functional during outages.
Why is decentralized storage hosting not a 'set and forget' task?
Managed hosting services can change terms or discontinue products, as seen with Fleek's legacy service. Teams must maintain an exit plan, control their own pinning accounts, and ensure content hashes are recorded durably.

By Chloe Redfern