Why we picked Solana for per-request AI inference payments
A 400ms finality target and ~$0.00025 per-transaction fee are not nice-to-haves for a decentralized inference market. They are load-bearing. Here is the engineering case.
When we tell people SolanaLM settles each inference request on Solana, the first question is usually some variant of “why not Ethereum L2s?” or “why not Cosmos?” or “why pay any settlement fee at all?”
The short answer: per-inference settlement only works if finality is faster than the user’s perception of “the request is done,” and if the fee is so much smaller than the inference revenue that it disappears into rounding. Solana is the only general-purpose chain that hits both targets today.
The long answer is this post.
The constraint: settlement must finish before the user does
A typical SolanaLM completion runs about 800ms to 4s end-to-end, depending on model and prompt length. The first token arrives in 50–200ms; the rest stream out at 30–80 tokens per second. By the time the user reads the response, the request is “done” from their perspective.
If settlement takes 12 seconds (Substrate-style chains), settlement is not part of the request — it is a deferred process that has to be tracked separately. That introduces:
- Dispute surface. If a node says “I served the request” and the gateway says “I never saw it land,” who is right? With pre-finality settlement, the answer is “wait 12 seconds and check the chain.” With sub-finality settlement, it is “you both watched the same block confirm.”
- Capital lockup. Pre-funding sessions to avoid per-request settlement means clients keep balance with the gateway. That is a custodial relationship we did not want to introduce.
- Operational complexity. Settlement-as-a-separate-process needs its own retry logic, its own dead-letter handling, its own observability. Settlement-inline gets all of that from the request lifecycle for free.
Solana’s ~400ms finality means we can fire-and-confirm inside the request handler. The Python looks roughly like:
async def serve_inference(request: InferenceRequest):
# Verify payment intent
payment_sig = await verify_solana_signature(
request.payment_intent,
wallet=request.wallet,
)
# Forward to node
response = await node_pool.dispatch(request)
# Settle immediately
await solana_client.send_transaction(
build_payment_tx(
from_wallet=request.wallet,
to_node=response.node_id,
amount=response.cost_sol,
memo=response.request_id,
)
)
return response
The send_transaction call resolves before the handler returns. The audit log captures the signature. There is no separate settlement process.
The constraint: fees must disappear into rounding
A typical SolanaLM inference request earns the node somewhere between 0.0001 and 0.001 SOL (a few cents at current prices). For settlement to make economic sense, the network fee has to be a small fraction of that revenue — call it sub-10% in the worst case.
Solana network fees are roughly 0.000005 SOL per signature, or about $0.00025. As a fraction of even the smallest inference revenue (0.0001 SOL), that is 5%. As a fraction of a typical request (0.0005 SOL), it is 1%. As a fraction of a large request (0.001 SOL), it is 0.5%.
Compare:
- Ethereum mainnet: variable, often $1–10 per transaction. Inference revenue would have to be implausibly high for this to work.
- Optimistic L2s (Arbitrum, Optimism, Base): roughly $0.01–0.05 per transaction. Better, but still 10–50% of typical inference revenue, and finality periods are L1 settlement times, not L2 block times, depending on your threat model.
- Cosmos chains: variable per chain, generally low fees. Settlement times typically 5–7s. Not bad, but not as fast as Solana.
- Solana: ~$0.00025, ~400ms finality.
Solana is the only mainstream general-purpose chain that meets both targets cleanly. We did not pick it because we like Solana; we picked it because the alternative was building a custom rollup just to settle inference, and that was not a fight we wanted to pick on top of building the actual product.
What the code looks like
The Solana integration is intentionally small. The full payment library is about 600 lines of Python wrapping solana-py. Here is the meaningful core:
from solana.rpc.async_api import AsyncClient
from solana.transaction import Transaction
from solders.system_program import TransferParams, transfer
from solders.keypair import Keypair
from solders.pubkey import Pubkey
class SolanaSettlement:
def __init__(self, rpc_url: str, protocol_wallet: Keypair):
self.client = AsyncClient(rpc_url)
self.protocol = protocol_wallet
async def settle(
self,
client_wallet: Pubkey,
node_wallet: Pubkey,
amount_sol: float,
request_id: str,
) -> str:
lamports = int(amount_sol * 1_000_000_000)
protocol_fee = int(lamports * 0.025)
node_payout = lamports - protocol_fee
tx = Transaction()
tx.add(transfer(TransferParams(
from_pubkey=client_wallet,
to_pubkey=node_wallet,
lamports=node_payout,
)))
tx.add(transfer(TransferParams(
from_pubkey=client_wallet,
to_pubkey=self.protocol.pubkey(),
lamports=protocol_fee,
)))
result = await self.client.send_transaction(tx)
await self.client.confirm_transaction(result.value)
return str(result.value)
The 2.5% protocol fee is split inline. The settlement signature becomes the audit log primary key. Done.
Where this gets harder
We are not claiming Solana is magic. A few honest gotchas:
RPC reliability. Mainnet RPC nodes sometimes lag or rate-limit you. The gateway needs to handle multiple RPC endpoints with health-checked failover. We use Helius and Triton as primaries with Solana’s public RPC as fallback.
Transaction expiry. Solana transactions are valid for ~60s after the recent blockhash they reference. Long-running requests need to re-sign if they overrun. Our handler resigns automatically on expiry.
Network congestion. Solana has had stability incidents. When the network is degraded, settlement falls back to a queue with retry. Requests still complete; payments may be delayed by minutes. We surface this in the admin dashboard.
Compute unit pricing. Solana introduced priority fees. We bid modestly to keep transactions in the next block. This is an additional configurable cost we expose to operators.
What this enables
Sub-second settlement is not just an optimization. It enables product shapes that defer-settle chains cannot reach:
- Streaming pay-as-you-go. A client can pay per token rather than per request. Each generated token triggers a tiny settlement.
- Real-time slashing. A node that returns garbage gets stake reduced inside the same block as the bad response.
- Trust-minimized streaming. A client can verify it is paying for actual streamed output, not a settled-after-the-fact aggregate.
We are not using all of these yet. We built the foundation that lets us reach them without re-architecting.
Could we have used something else?
Probably. Aptos and Sui have comparable finality and fee profiles. Monad is launching soon with similar targets. NEAR’s sharded model could work. We picked Solana because the SDK ecosystem (solana-py, anchor-lang) is the most mature for our needs, and because the chain has battle-tested itself in production for years.
If you are building something similar and Solana feels wrong for your team, the design generalizes. The protocol is chain-neutral; only the settlement library cares which chain. Forks are welcome.