Skip to main content

Going to Production

Working on a testnet is not the same as being production-ready. Mainnet has real value, real users, and irreversible transactions. This page is a checklist for the jump: each item links to the canonical guide for that concern, so treat it as a map rather than a tutorial.

1. Test thoroughly

  • On-chain validators: your validators are pure functions, so test them exhaustively with mock transactions. See Testing, and use the fuzzer for property-based coverage (Optimization).
  • Off-chain code: test transaction building and submission too. Evolution ships unit tests, an emulator, and devnet integration tests (Testing your off-chain code).
  • Rehearse on Preprod: Preprod mirrors mainnet (same protocol parameters and epoch length). Do a full dry run of your user flow there before mainnet. See Networks & test ADA. Mainnet transactions cannot be reversed, so the burn-in happens here.

2. Secure it

  • Guard the vulnerability classes: datum hijacking, double satisfaction, token forgery, resource exhaustion. See Smart contract security, and sharpen your eye on the CTF.
  • Get an audit: for any contract holding meaningful value, a professional audit is standard practice before mainnet. Testing finds the bugs you thought of; audits find the ones you didn't.
  • Keep keys and secrets safe: the frontend should only sign; build and submit on a backend (frontend signs, backend submits). Never ship provider API keys in client-side code. Review key & wallet security.

3. Make transactions reliable

The most common production failure mode is a transaction rejected because an input was already spent or an indexer lagged.

  • Retry safely: structure build → sign → submit so retries re-read chain state instead of replaying a stale UTxO. See resilient submission.
  • Chain multi-step flows: build dependent transactions up front without waiting for confirmation between steps. See transaction chaining.
  • Handle errors structurally: distinguish recoverable (stale input, provider hiccup) from terminal (insufficient funds) failures. See Error handling.

Harden your provider

A single managed API is a single point of failure, and chatty code can hit its rate limits. Two patterns fix this, and both rest on the same idea: a provider is a pluggable data source behind a common interface, so you can stack or swap providers without touching transaction-building code.

  • Failover: try the next provider when one errors, so a single outage doesn't take you down.
  • Caching: memoize slow-changing reads (protocol parameters, asset metadata) for a short window to cut redundant calls.

How you get there differs by SDK: one ships failover as configuration, the other gives you a small interface to assemble it yourself.

Evolution has failover built in. Wrap your providers in a MultiProvider with a priority strategy (try them in order) or round-robin (spread load), and it switches automatically on a provider error, accumulating the failures for debugging:

// priority: try provider 1, fall through to 2 on error
const strategy = {
type: "priority",
providers: [
{ provider: blockfrost, priority: 1 },
{ provider: koios, priority: 2 },
],
}
// or spread requests evenly: { type: "round-robin", providers: [...] }

See the Evolution provider docs for wiring MultiProvider into a client. Pointing at your own indexer or node beyond the four built-in providers is an advanced, internal path.

4. Optimize

  • On-chain cost (ExUnits): smaller, faster validators mean lower fees and more headroom under the per-transaction and per-block limits. See Optimization and the execution-cost model.
  • Off-chain efficiency: coin selection and change management affect transaction size and UTxO fragmentation. See Performance.

5. Choose your infrastructure

Decide how your dApp will read and submit to the chain: a managed API (fastest to ship) or your own node and indexer (most control). See Production infrastructure for the full decision.

6. Smooth the on-ramp

Production also means users who may not have a wallet or any ADA. Lower the barrier:

  • Wallet-as-a-Service: let users create a non-custodial wallet with social login (connect a wallet).
  • Transaction sponsorship: pay fees on behalf of users so they can transact before holding ADA (sponsorship).

Checklist

  • Validators and off-chain code covered by tests; full flow rehearsed on Preprod
  • Security reviewed; audit done for value-bearing contracts
  • Frontend signs only; provider keys server-side
  • Transactions are retry-safe; errors handled by category
  • On-chain and off-chain paths optimized within limits
  • Infrastructure chosen (managed vs self-hosted) and load-appropriate
  • Onboarding path decided (browser wallet, WaaS, sponsorship)

Next steps