The testnet worked. Production is different. Gas price spikes, RPC node reliability, transaction finality assumptions, and the bridge you forgot to think about — these are the things that make blockchain production hard.
This is not a criticism of testnet development. Testnet is the right way to build and validate contracts. The problem is that testnet environments are optimized for development velocity: reliable RPC endpoints, stable gas prices, instant finality, and no one else competing for block space. Production is a different operating environment, and the teams that fail in production are the ones that deployed testnet assumptions without auditing them.
We shipped the Sigil image provenance system on Polygon mainnet. See the Sigil engagement for the full account — the architecture decisions, the production incidents we prevented by building for them, and what the operational picture looks like at scale.
What "production-ready" means on Polygon
Production-ready means your system handles the failure modes of the production environment gracefully. On Polygon, those failure modes are different from what you encounter in a normal web application, and they're different from what you encounter on testnet.
Testnet has one RPC endpoint that is up when you need it, gas prices are 0.01 gwei, and finality is fast. Production Polygon mainnet has RPC nodes that go down and throttle without notice, gas prices that spike 50–100x in seconds during network congestion, and finality that requires understanding re-org depth. Each of those differences requires a design response.
The RPC node decision
Public RPC endpoints are where most teams start. They work fine for development and low-volume production. They are not appropriate for production systems that have any of the following: latency requirements, reliability requirements, or query volume above a few requests per second.
The public endpoints are rate-limited. The rate limits are not published and are not enforced uniformly. You will discover the limits in production, under load, at a time when you can least afford the investigation. The limits are also not the only reliability issue: public endpoints are shared infrastructure, which means their performance is affected by the traffic patterns of every other team using the same endpoint.
Dedicated RPC infrastructure — from providers like Alchemy, Infura, or QuickNode on their paid tiers, or from running your own full node — provides rate limits you control, SLAs you can hold someone to, and dedicated capacity. The cost difference between the free public endpoint and a dedicated endpoint is $50–$500/month depending on volume. The cost difference in engineering time spent debugging RPC-related production incidents is much larger.
Run two providers, not one. Set up automatic failover. The failover should be at the application layer — your web3 client should detect RPC errors and route to the backup endpoint. This is not complex to implement and it eliminates the single point of failure.
A dedicated archive node matters if your application needs historical state access — contract events from more than 128 blocks ago require archive data, which most light RPC providers do not serve. If your application reads historical events on user request (a common pattern in provenance and audit applications), you need archive access either from a provider or your own node.
Gas management
Gas management is the area where testnet assumptions fail most visibly in production, because the failure manifests as real money lost to users or transactions that never complete.
Estimation. The standard approach — call eth_estimateGas before submitting a transaction — works most of the time and fails in the cases that matter. estimateGas returns an estimate based on the current state of the chain. If the state changes between estimation and submission (because another transaction was included first), the estimate may be wrong. For user-facing transactions that involve token transfers or state changes with variable gas costs, add a buffer of 20–30% above the estimate. Users prefer slightly higher gas costs to failed transactions.
Price strategy. On Polygon, the EIP-1559 fee market means you're setting both a maxFeePerGas (the ceiling) and a maxPriorityFeePerGas (the tip to the validator). The right approach is not to hardcode these values or to blindly use the RPC node's fee estimate. Use a gas price oracle — Polygon's gas station API or equivalent — and set your ceiling dynamically based on current network conditions.
For user-facing transactions where confirmation time matters: set the priority fee aggressively enough that your transaction is included in the next 1–2 blocks under normal conditions. For batch transactions or background operations where latency doesn't matter: set conservative fees and accept slower inclusion.
Stuck transaction recovery. Transactions get stuck. A transaction with a fee that was appropriate when it was submitted may be repriced below the minimum as the gas market moves. The recovery pattern: submit a replacement transaction with the same nonce but a higher fee. This requires your application to track pending transactions, monitor their inclusion status, and automatically resubmit with bumped fees after a defined timeout. If you don't build this, stuck transactions are a support event.
The implementation requires a transaction manager that maintains state across the submission → pending → included lifecycle. This is not a default in most web3 libraries. Build it explicitly.
Event listening and re-org handling
Events are how your application learns what happened on-chain. The naive implementation — listen for events, process them, done — breaks in production in two ways: RPC disconnections and chain reorganizations.
RPC disconnections. WebSocket connections to RPC nodes disconnect. This is normal. Your event listener needs to detect disconnection, reconnect automatically, and replay any events that were emitted during the disconnection window. The replay window requires you to track the last block you processed. On reconnect, query for events from lastProcessedBlock to currentBlock before resuming the live listener.
Re-organizations. Polygon's finality model means that blocks below a certain depth are canonical. Blocks above that depth can be reorganized — replaced by a different chain of blocks as the network resolves competing chains. On Polygon PoS, the practical re-org depth is small (1–5 blocks in the vast majority of cases), but it is not zero, and it is not guaranteed.
If your application processes events and takes action based on them — minting tokens, updating database state, sending notifications — you need to wait for confirmation depth before treating an event as final. The typical production threshold is 128 blocks on Polygon (approximately 4 minutes at 2-second block time). For lower-stakes operations, 30–50 blocks is a reasonable tradeoff between latency and safety.
The implementation: a two-phase processing pipeline. Phase one: ingest events and store them with their block number as "pending." Phase two: promote events to "confirmed" when their block depth exceeds the threshold. Application logic runs against confirmed events only.
The bridge layer
If your application involves assets that move between Polygon and Ethereum mainnet (or between Polygon and another L2), you have a bridge dependency. Bridges are one of the highest-risk components in any cross-chain application, and they deserve explicit architectural treatment.
The Polygon PoS bridge has a known withdrawal delay (7 days for Ethereum exits). Your application needs to model this correctly — users who initiate a withdrawal should understand the timeline, and your system should track the multi-stage withdrawal lifecycle (initiated → checkpoint included → exit claimable → claimed).
If you're using a third-party bridge (LayerZero, Axelar, or similar), understand the trust model. These bridges have different security assumptions from the canonical bridge. Your product's risk disclosure should accurately reflect which bridge is in use and what its assumptions are.
The operational implication: bridge transactions require monitoring at each stage. A bridge transaction that is stuck at the "checkpoint included" stage requires different remediation than one stuck at "exit claimable." Your monitoring needs to distinguish between these states.
Monitoring and alerting
Blockchain-specific monitoring requires signals that don't exist in normal application monitoring.
Transaction inclusion lag. Time between transaction submission and inclusion in a block. A spike in this metric indicates gas market congestion that may require fee adjustment. Alert at 2x the normal inclusion time.
Pending transaction depth. How many transactions are in your pending pool, waiting for inclusion. A growing pending pool indicates that submitted fees are consistently below the market rate.
Re-org depth. Track the maximum re-org depth observed in the last 24 hours. Sudden increase in re-org depth is a signal to raise your confirmation threshold temporarily.
Event processing lag. The gap between the current block and the last block your event processor has confirmed. Normal operation should be within a few blocks. A growing lag indicates that your event processing pipeline is falling behind — either due to RPC issues or processing bottlenecks.
Contract balance monitoring. If your contracts hold ETH or tokens (for gas subsidies, escrow, or protocol fees), monitor balances and alert before they fall to dangerous levels. A contract that runs out of gas balance at the wrong moment is a production incident.
The operational playbook for the first 90 days
Days 1–30: monitor everything, touch nothing. Your initial deployment is a data collection exercise. Observe actual gas prices, actual RPC reliability, actual transaction inclusion times. Compare against your testnet assumptions. The gaps are your optimization backlog.
Days 31–60: tune the gas strategy based on real data. Adjust fee estimation buffers, confirmation thresholds, and stuck transaction recovery timeouts based on what you've observed. Add alerting on the metrics that actually matter for your use case.
Days 61–90: optimize for the patterns you've observed. If users are experiencing slow confirmations during specific hours, tune fee strategy for those windows. If your event processor is consistently behind during high-activity periods, add processing capacity. Build the runbook: for each alert, what is the expected response?
This is for you if
You're building a production Web3 application on Polygon — provenance, DeFi, gaming, tokenization — with real contracts, real users, and real economic stakes. You've done testnet development and need to make the production transition correctly.
Engagements for Polygon production infrastructure are part of larger build engagements ($75k–$200k), where the smart contract architecture and the off-chain infrastructure are designed and deployed together. We do not build memecoins, speculative tokens, or contracts designed for market manipulation.
This is for founders who are building systems where the blockchain layer provides genuine utility — provenance, verifiability, programmable settlement, or asset ownership — and who understand that the operational requirements of running that infrastructure in production are different in kind from what testnet development requires.