The Sub-50ms Edge: Architecting Zero-Overhead Solana Execution Engines via Yellowstone gRPC and Shredstream Pipelines
An engineering deep dive into architecting low-latency Solana execution engines using Yellowstone gRPC, raw shred pipelines, pre-parsed program feeds, and persistent transaction submission.
On this page +
The fundamental resource in competitive Solana execution is no longer throughput. It is freshness: how quickly a system can acquire authoritative state, turn it into a decision, construct a transaction, and place that transaction onto the correct network path. This whitepaper walks the full pipeline, from raw shreds and Yellowstone gRPC through pre-parsed program feeds to persistent UltraSend egress, and shows where every unnecessary millisecond hides.
Technical scope and current-network note#
In latency-sensitive Solana systems, terminology matters.
“Sub-50ms” in this paper refers to the application data plane: the interval between useful infrastructure-level information becoming observable and a trading engine producing and transmitting its reaction. It does not mean that a Solana transaction can universally achieve irreversible finality in 50 milliseconds. As of October 6, 2026, Solana mainnet had not yet activated Alpenglow; TowerBFT remained the mainnet consensus regime. Alpenglow targets roughly 150ms finality when activated, while leaving transaction execution itself largely unchanged (solana.com).
Similarly, “Shredstream” is used as an architectural term for direct low-latency shred delivery. Jito’s official documentation scheduled its legacy hosted Jito ShredStream service for complete shutdown on September 5, 2026. NoLimitNodes provides a Jito-compatible raw-shred delivery path that preserves the receiver/deshredder architecture without depending on the retired hosted Jito service (docs.jito.wtf).
Finally, “zero-overhead” should be understood as zero unnecessary parsing, copying, polling, queuing, and connection setup on the critical path. Physics, kernel scheduling, cryptography, protobuf decoding, signature generation, packet transmission, and validator execution still consume time.
01Abstract and executive summary#
The fundamental resource in competitive Solana execution is no longer simply throughput. It is freshness: how quickly a system can acquire authoritative state, transform that state into a strategy decision, construct an executable transaction, and place that transaction onto the correct network path.
A conventional trading architecture commonly resembles:
Solana
|
v
Shared JSON-RPC
|
+--> HTTP polling
|
+--> WebSocket JSON notifications
|
v
JSON/Base64 decode
|
v
Anchor/Borsh parser
|
v
State reconstruction
|
v
Strategy
|
v
Build transaction
|
v
JSON-RPC sendTransaction
This architecture is convenient. It is also poorly matched to the requirements of high-frequency execution.
At scale, the dominant problem is not one enormous bottleneck. It is the accumulation of small, variable delays: provider-side RPC processing, JSON serialization, UTF-8 parsing, Base64 transformations, heap allocations, local IDL dispatch, WebSocket queueing, garbage collection, account-state reconstruction, network round trips, transaction serialization, TLS reconnects, and finally transaction propagation.
For a latency-sensitive system, the appropriate abstraction is:
T_reaction = T_ingestion
+ T_deserialization
+ T_strategy
+ T_serialization
+ T_network
Every component is both a median-latency problem and, more importantly, a tail-latency problem.
NoLimitNodes addresses these layers through separate but composable infrastructure:
- Yellowstone gRPC for direct Geyser-derived, strongly typed, filterable Solana streams.
- Raw Shredstream delivery for applications requiring block data earlier in the propagation lifecycle.
- Enhanced and Program Streams for server-decoded Pump.fun, Raydium, Orca, Meteora and other protocol data.
- Low-latency Solana RPC for conventional state queries and compatibility.
- UltraSend for persistent HTTPS or QUIC transaction submission.
NoLimitNodes’ current Program Streams catalog exposes 1,074 topics across 37 programs, with schema discovery and JSON or Protobuf delivery (docs).
The resulting design principle is straightforward:
Move everything that does not differentiate the trading strategy out of the strategy’s critical path.
A trading firm should spend CPU cycles on price discovery, risk, opportunity classification, transaction construction and signing, not on repeatedly decoding protocol layouts that every other participant also has to decode.
The competitive edge therefore does not come from gRPC alone, Shredstream alone, or a faster RPC alone. It comes from constructing a pipeline in which no unnecessary transformation exists between the earliest usable Solana signal and the outbound transaction.
02Solana’s architectural bottleneck for quant traders#
2.1 Understanding the Solana execution path
A low-latency execution engine must be designed around the lifecycle of a Solana transaction rather than around the RPC API exposed to ordinary applications.
Trader | | signed transaction v TPU ingress | | UDP / QUIC v Leader | +--> signature verification +--> sanitization +--> compute-budget / age checks +--> account loading +--> scheduling +--> SVM execution +--> account commit | v Entries | v Shreds | +------------------------------+ | | v v Network propagation Geyser notifications | | v v Validators/RPC Yellowstone gRPC
The historical Solana architecture is frequently described through four concepts: Proof of History, Gulf Stream, leader scheduling, and Turbine/shreds.
Proof of History
Under TowerBFT, Proof of History is part of the mechanism that establishes ordering and the progression of slots. It supplies a cryptographically verifiable sequence through which nodes reason about transaction ordering and time.
Alpenglow changes that. Solana’s upgrade documentation states that Alpenglow removes PoH as the mechanism pacing block production; it also changes several assumptions for Geyser consumers, including the introduction of bank_id. At the time of writing, Alpenglow was active on testnet and devnet but not mainnet (solana.com).
Production engines should therefore be written for both realities:
Today (TowerBFT):
slot -> bank -> PoH/entries -> shreds -> TowerBFT confirmation
Alpenglow-ready:
slot -> potentially multiple candidate banks
|
+--> bank_id A
+--> bank_id B
|
v
Votor chooses winner
An application that assumes slot uniquely identifies a candidate block will eventually be incorrect. Newer Geyser/Yellowstone pipelines need to key relevant buffers by (connection, slot, bank_id) and reconcile different providers using block hashes rather than comparing bank_id, because bank IDs are local to a node.
Leader scheduling and Gulf Stream
Solana does not rely on the conventional global public mempool familiar from Ethereum-style systems.
The validator scheduled to produce a future slot is known in advance. Transaction-forwarding mechanisms can therefore direct traffic toward current and upcoming leaders instead of waiting for a global mempool election. Historically, this design has been described as Gulf Stream.
For a trader, the practical implication is significant:
T_propagation != T_broadcast-to-entire-network
The objective is to get the signed transaction into an effective path toward the validator that can actually execute it.
Consequently, geographical distance to generic RPC infrastructure is a weak optimization target compared with distance and routing quality toward leader-aware transaction infrastructure.
TPU ingress
A validator’s Transaction Processing Unit receives transactions through its network ingress. Modern Solana transport includes QUIC paths, with the validator performing a sequence of checks before a transaction enters actual execution.
Network packet
|
v
deserialize wire transaction
|
v
signature verification
|
v
sanitize
|
v
blockhash / age / fee checks
|
v
load accounts
|
v
schedule conflicting transactions
|
v
execute in SVM
|
v
commit
The trading engine cannot eliminate these validator-side costs. It can eliminate nearly everything unnecessary before the transaction reaches them.
2.2 The true latency equation
The user-visible equation is a single sum. A production quantitative system should instrument a more granular form, and should keep reaction, landing, and finality strictly separate:
User-visible:
T = T_ingestion + T_deserialization + T_strategy_logic
+ T_serialization + T_network_propagation
Instrumented reaction time:
T_react = T_source_observation + T_transport_in
+ T_decode + T_state_update + T_strategy
+ T_tx_build + T_sign + T_transport_out
Landing:
T_land = T_react + T_leader_queue + T_scheduler + T_execution
Confirmation / finality:
T_final = T_land + T_consensus
These numbers must never be conflated.
A provider may legitimately deliver an event in less than 50ms while the user’s transaction still lands considerably later because the current leader, account contention, compute budget, fee bid, network topology or slot boundary dominates the remaining path.
2.3 Why traditional HTTP JSON-RPC becomes expensive
JSON-RPC is an excellent compatibility interface. It is not an ideal wire format for a high-frequency state machine.
Consider an RPC result containing binary Solana data. It may experience:
- serialization into an RPC representation
- Base58 or Base64 encoding
- insertion into a JSON document
- HTTP framing
- TLS/TCP transport
- UTF-8 JSON parsing by the client
- extraction of the encoded field
- Base64 decoding
- transaction/account decoding
- program-specific instruction decoding
None is individually catastrophic. Together they increase compute usage and latency variance.
A badly designed strategy then adds periodic calls such as:
getSlot getAccountInfo getMultipleAccounts getLatestBlockhash getSignatureStatuses
The result is a request-response dependency graph in which freshness is limited by polling frequency:
expected polling detection delay ~= delta_poll / 2 100ms poll interval -> ~50ms average detection delay 10ms poll interval -> ~5ms average delay, 10x the RPC load
A 100ms polling loop has approximately 50ms average detection delay before the network stack, provider execution or parsing is considered. Polling every 10ms instead does not solve the architecture; it multiplies RPC load by ten.
Connection setup and jitter
TCP is not inherently inappropriate for low latency. Repeatedly creating connections is.
DNS -> TCP establishment -> TLS handshake -> HTTP request -> server dispatch -> response
Production systems must instead maintain warm persistent channels.
2.4 WebSockets are better, but not the end state
A common oversimplification claims that HTTP is pull while both WebSockets and gRPC magically eliminate all latency. WebSockets are already push-based. That distinction matters.
The problem is that conventional Solana WebSocket APIs generally expose RPC-layer subscriptions with JSON representations and a less expressive filtering model than the underlying Geyser stream.
Validator | v internal runtime state | v RPC/PubSub processing | v JSON serialization | v WebSocket | v client JSON parser
Validator | v Geyser callback | v Yellowstone filter | v Protobuf / HTTP2 stream | v typed client
NoLimitNodes documents Yellowstone as receiving data through direct Geyser access before the normal RPC processing layer, with bidirectional filtering for accounts, transactions, blocks, slots and entries (gRPC docs). That is a more accurate explanation of the advantage than simply saying “gRPC is push.” For a deeper comparison, see Yellowstone gRPC vs WebSockets.
2.5 Local Anchor and Borsh decoding as a hot-path tax
After acquiring raw bytes, many trading systems immediately create a second bottleneck: their own decoder. For an Anchor-based program, a local parser commonly performs something conceptually similar to:
instruction bytes
|
+--> identify program
|
+--> inspect discriminator
|
+--> map discriminator -> instruction/event type
|
+--> deserialize fields
|
+--> deserialize nested enums/vectors/options
|
+--> map account indexes
|
+--> resolve address lookup tables
|
+--> inspect inner instructions / CPI
|
+--> normalize into strategy representation
Historically, developers often assumed Anchor discriminators were always eight bytes. Anchor 0.31 introduced custom-length discriminators: eight bytes remain the default, but hardcoding that length is no longer a safe general assumption (anchor-lang.com). And not every Solana protocol is Anchor-based.
A production decoder therefore needs to track:
- Anchor IDLs
- custom Borsh layouts
- protocol-specific enums
- versioned instruction layouts
- account discriminators
- event layouts
- inner/CPI instructions
- program upgrades
- address lookup tables
- SPL Token versus Token-2022 differences
- optional extensions
- new accounts and deprecated accounts
The real cost is not a single borsh::deserialize() invocation. It is maintenance plus hot-path branching plus memory behavior.
At hundreds of thousands of messages per second, repeated temporary allocations can create allocator contention, cache pollution and unpredictable pauses. In garbage-collected environments such as Node.js or Python, transient object creation can also create latency spikes far larger than the median decoding cost.
For trading infrastructure, p99 and p99.9 behavior matter more than an attractive microbenchmark average.
03Architecting low-latency data ingestion: Yellowstone gRPC vs traditional RPC#
3.1 Geyser as the appropriate streaming boundary
Solana’s Geyser interface exists inside the validator data pipeline. Yellowstone Dragon’s Mouth converts that high-frequency stream into a remotely consumable gRPC API.
NoLimitNodes currently exposes Yellowstone at:
with raw gRPC authentication through x-api-key. Current Yellowstone functionality includes filtered subscriptions for accounts, transactions, transaction statuses, slots, entries, blocks and block metadata. The stream is bidirectional, allowing filters to be modified without reconnecting (gRPC docs).
+--> HTTP RPC query
|
Solana validator ----------+--> RPC WebSocket subscription
|
+--> Geyser ---------+--> Yellowstone gRPC
For a quant system, Geyser is often a better data-plane boundary because the engine receives precisely the subset of state it needs rather than repeatedly interrogating an RPC abstraction. See our Geyser plugin guide for the validator-side mechanics.
3.2 Filter at the producer, not the strategy engine
Suppose a strategy cares about transactions touching only:
- Pump.fun
- Raydium CPMM
- several monitored wallets
- a particular set of token accounts
A naïve design receives a broad firehose and discards irrelevant messages client-side. A better design filters as early as possible, which improves three resources simultaneously:
filter before network -> filter before deserialize -> filter before strategy bandwidth DOWN cpu DOWN queue pressure DOWN
Queue pressure is particularly important. If event production temporarily exceeds consumption, the backlog grows linearly with the gap:
if lambda_producer > mu_consumer then Q(t + dt) = Q(t) + (lambda - mu) * dt
A pipeline that is nominally “5ms fast” can become hundreds of milliseconds stale under burst load. The correct production response is not an unbounded queue. It is:
- upstream filtering
- bounded channels
- overload metrics
- workload shedding where semantically safe
- parallel independent subscriptions
- explicit reconnect/replay behavior
3.3 Protobuf versus JSON
The principal advantage of protobuf is not that every protobuf operation always beats every JSON library by a fixed percentage. It is the more predictable representation.
Independent serialization benchmarks generally show protobuf-style binary formats delivering substantial size and parsing advantages over JSON for suitable structured workloads, although exact ratios vary dramatically with schema and implementation. A serious trading firm should benchmark its actual payloads, not quote an ecosystem-wide multiplier.
The relevant benchmark is:
p50 decode time p95 decode time p99 decode time p99.9 decode time allocations/message bytes/message CPU cycles/message maximum sustainable messages/second
3.4 Yellowstone SubscribeDeshred
An especially important development for pre-execution applications is Yellowstone’s deshred stream. Current Yellowstone service definitions include both:
Subscribe(...) SubscribeDeshred(...)
The latter can surface deshredded transactions before normal execution-derived metadata is available. The tradeoff is obvious: pre-execution information cannot carry the same post-execution truth as a transaction status containing TransactionStatusMeta.
PRE-EXECUTION PATH
------------------
shreds/deshred
|
+--> fastest possible observation
|
+--> no definitive execution outcome yet
POST-EXECUTION PATH
-------------------
Geyser processed transaction
|
+--> execution result / metadata
|
+--> later but semantically richer
A sophisticated engine often consumes both.
3.5 Shredstream: moving observation earlier
A shred represents a portion of ledger data propagated between Solana nodes. A raw shred receiver shifts the observation boundary earlier:
Leader
|
| produces entries
v
Shred encoding
|
+---------> conventional propagation --------> remote validator
|
+---------> low-latency raw shred feed ------> HFT receiver
|
v
dedupe
|
v
FEC recovery
|
v
deshred
|
v
entries
|
v
transactions
Legacy Jito documentation explicitly positioned ShredStream as a low-latency shred path and documented local deshredding into transactions. Jito also announced that its hosted service would shut down September 5, 2026 (docs.jito.wtf). NoLimitNodes now exposes a Jito-compatible raw-shred path, allowing compatible receivers to preserve their existing UDP/deshred architecture (Jito ShredStream vs NoLimitNodes).
This matters because a shred feed and Yellowstone solve different problems.
- Shredstream optimizes earliest observation.
- Yellowstone optimizes structured validator-state consumption.
- Program/Enhanced Streams optimize semantic decoding.
They are complementary rather than interchangeable. Our Shredstream guide covers the receiver side in detail.
3.6 The three-tier ingestion architecture
A production NoLimitNodes execution engine can therefore run three concurrent lanes:
SOLANA
|
+----------------+----------------+
| | |
v v v
Raw Shreds Yellowstone Program/Enhanced
| | |
deshred raw typed decoded semantic
| state events
v v v
pre-execution execution/ Pump.fun/Raydium/
intelligence account state Orca/Meteora/etc.
| | |
+----------------+----------------+
|
v
STRATEGY STATE
|
v
EXECUTION ENGINE
|
v
UltraSend
The fastest system does not force every signal through the same abstraction.
04Eliminating parser overhead with NoLimitNodes pre-parsed feeds#
4.1 Parser maintenance is infrastructure debt
Suppose a trading organization supports:
- Pump.fun
- PumpSwap
- Raydium AMM v4
- Raydium CPMM
- Raydium CLMM
- Orca Whirlpools
- Meteora DLMM
- Jupiter
- Kamino
Without managed decoding, each protocol becomes an internal software product. Teams must answer:
- Which program IDs are active?
- Which versions exist?
- Which discriminators map to which messages?
- Has an account layout changed?
- Are new fields optional?
- Did the protocol introduce a second instruction with a similar semantic meaning?
- Is an emitted event in logs, CPI data, account state or instruction arguments?
- Does the parser understand Token-2022?
- Which IDL version generated the client’s bindings?
- How is historical compatibility preserved?
4.2 Server-side semantic decoding
NoLimitNodes Program Streams currently publishes a catalog of 1,074 topics across 37 Solana programs and exposes three RPCs:
ListTopics GetTopicSchema Subscribe
Topics follow a program-dot-instruction naming scheme:
solana.<program>.<instruction_or_event> solana.pump_fun.trade_event solana.raydium_amm_v4.swap solana.kamino_lending.deposit
Each Program Streams response carries a topic, slot and payload. JSON returns already-decoded JSON; Protobuf mode returns a Base64 representation of the topic-specific protobuf message, whose schema can be obtained through GetTopicSchema (Program Streams overview).
The useful abstraction becomes:
BEFORE ------ raw transaction -> program dispatch -> instruction dispatch -> IDL lookup -> Borsh decode -> event decode -> normalize -> strategy WITH PRE-PARSED FEED -------------------- typed protocol event -> strategy
For example, the documented Pump.fun TradeEvent exposes 25 fields including mint, SOL amount, token amount, buy/sell direction, user, reserves, fee information, creator information and protocol state. Its topic is solana.pump_fun.trade_event (topic page).
4.3 “Zero-copy” must be defined carefully
A true end-to-end zero-copy pipeline is generally impossible once data crosses process, kernel and network boundaries. The engineering goal is therefore:
Minimize copies and object construction after the bytes enter each process.
NoLimitNodes does not publicly document every internal implementation detail of its proprietary decoder. Therefore an authoritative whitepaper should not invent claims about a specific allocator or internal ring-buffer implementation. A high-performance reference implementation for this class of server-side decoder would look like:
NIC RX | v bounded receive buffer | v program-id classifier | v discriminator / instruction classifier | v decode directly from byte slice | v normalized typed representation | +--> Protobuf encode | v preallocated bounded subscriber queues | v gRPC
Performance-sensitive implementation principles are:
- avoid constructing full transaction objects when only one instruction is required
- borrow byte slices where possible
- precompute program/discriminator dispatch tables
- avoid strings in the parser
- use bounded queues
- separate decode workers by program or partition
- reuse buffers
- emit typed protobuf structures rather than generic dynamic maps
At the consumer, protobuf again avoids recreating the entire local parsing stack.
4.4 Program Streams versus Enhanced Streams
NoLimitNodes exposes two semantic layers.
Program Streams preserve protocol-specific instructions/events and let the consumer choose JSON or Protobuf. Program Streams’ protobuf payload is Base64 text inside the response envelope, so the consumer performs one Base64 decode before protobuf decoding.
Enhanced Streams provide curated normalized feeds, and their protobuf payload is carried as bytes, eliminating that Program Streams-specific Base64 step (payload formats).
For maximum throughput:
raw Yellowstone -> most control Enhanced protobuf -> lowest semantic-client overhead Program protobuf -> maximum protocol coverage + typed schemas Program JSON -> easiest debugging/integration
4.5 The important latency boundary
NoLimitNodes currently publishes that its Pump.fun TradeEvent Program Stream is delivered in under 50ms from on-chain confirmation. This is a NoLimitNodes vendor-published figure rather than an independent measurement in this paper (topic page).
The qualifier “from on-chain confirmation” matters. A pre-parsed confirmed event is ideal for:
- immediate state updates
- cross-market reactions
- post-trade inventory management
- market-making model updates
- historical/live feature parity
It cannot retroactively create a pre-execution signal for the transaction that caused it. For that use case, the raw-shred/deshred lane is required. The fastest architecture therefore uses semantic and temporal separation:
Shreds -> "What may be about to happen?" Processed Geyser -> "What just executed?" Parsed Events -> "What did it mean?" Confirmed state -> "What can I trust more strongly?"
05Production implementation guide and benchmarks#
5.1 Reference execution architecture
A production deployment should separate ingestion, state, strategy and execution:
+------------------------+
| NoLimitNodes Shreds |
+-----------+------------+
|
v
Deshredder
|
+---------------------+
|
+--------------------+ v
| Yellowstone gRPC | --------------------> State Engine
+--------------------+ |
|
+--------------------+ |
| Program Streams | --------------------------+
+--------------------+ |
v
Strategy Core
|
v
Transaction Factory
|
v
Signer
|
v
Persistent UltraSend
QUIC / HTTPS
|
v
Solana Leader Path
The key design rule is that the strategy thread should never wait for:
- DNS
- TLS establishment
- IDL loading
- blockhash RPC
- dynamic schema discovery
- disk I/O
- log formatting
- metrics export
- database writes
All of those belong off the hot path.
5.2 Rust project layout
A practical client can maintain the official stream proto in the repository and generate tonic bindings during the build.
nln-engine/
├── Cargo.toml
├── build.rs
├── proto/
│ └── program-streams.proto
└── src/
├── main.rs
├── stream.rs
├── strategy.rs
├── transaction.rs
└── ultrasend.rs
The current official Program Streams service is nln.stream.v1.StreamService, and NoLimitNodes documents downloading the current proto rather than recreating it by hand (quickstart). An illustrative dependency set is:
In production, dependencies should be reproducibly pinned in Cargo.lock, not updated automatically on deployment machines.
5.3 Connecting to Program Streams with x-api-key
NoLimitNodes’ current authentication matrix specifies x-api-key metadata for raw Yellowstone, Enhanced Streams and Program Streams (authentication docs).
5.4 Consuming a Pump.fun typed event
The strategy should work against a typed domain object rather than transaction bytes.
These fields correspond to the current documented Pump.fun TradeEvent schema (topic page). Subscription:
There is no Anchor IDL lookup, discriminator switch or Borsh decoding in this client.
For the highest-volume production path, replace JSON with PROTO, call GetTopicSchema during deployment, generate a prost type from the returned topic schema, Base64-decode message.payload, and call:
NoLimitNodes explicitly recommends Program Streams protobuf for lower parsing overhead, strong field types and high-volume consumers (payload formats).
5.5 Strategy state should be allocation-poor
A high-frequency strategy core should receive compact immutable observations:
The event-ingestion layer can convert a large protocol event into the small feature vector actually required by the strategy. Do not pass giant generic JSON values through every layer. The preferred structure is:
wire representation
|
v
typed protocol object
|
v
minimal feature struct
|
v
strategy
5.6 Transaction construction
The outbound transaction should be mostly prepared before a signal arrives. Only genuinely dynamic components should be inserted on the hot path:
- recent blockhash
- amount
- slippage limit
- dynamic account
- compute-unit price
- optional tip
- signature
The exact imports depend on the Solana/Agave Rust crate family pinned by the project. Modern Solana SDK functionality is increasingly split among narrower crates, so a production repository should lock a tested dependency graph rather than copy “latest” package versions into the critical execution binary.
The important architectural behavior is stable:
precomputed accounts/instructions
+
cached recent blockhash
+
signal-dependent parameters
|
v
compile message
|
v
sign
|
v
serialize exactly once
5.7 Shredstream is ingress, not transaction egress
This distinction is operationally important. A shred stream transports observations of block data toward the trader. It is not the path on which the trader sends a transaction back to Solana.
INGRESS
NoLimitNodes raw Shredstream
|
v
trader
EGRESS
trader
|
v
NoLimitNodes UltraSend / RPC / leader routing
|
v
Solana validator
For NoLimitNodes-specific egress, UltraSend is the appropriate low-latency primitive.
5.8 UltraSend over persistent HTTPS
UltraSend currently accepts an already signed serialized Solana transaction and forwards the exact bytes; it does not simulate, rebuild, resign or replace the blockhash. The documented endpoints are (UltraSend overview):
HTTPS POST https://ultrasend.nolimitnodes.com/v1/transactions QUIC ultrasend.nolimitnodes.com:11000/UDP ALPN: ultrasend/1
A persistent HTTPS sender:
The Client must be created once when the engine starts, not once per order.
5.9 Persistent QUIC for the tightest egress path
When handshake overhead matters, UltraSend documents persistent QUIC as the lower-level alternative to HTTPS. The lifecycle should be:
process startup
|
+--> resolve endpoint
+--> create UDP socket
+--> QUIC handshake
+--> authenticate
|
v
KEEP CONNECTION WARM
|
+--> transaction
| |
| +--> open stream
| +--> write exact wire bytes
| +--> receive acknowledgment
|
+--> transaction
|
+--> transaction
Not:
signal -> DNS -> socket -> QUIC handshake -> transaction
The latter sacrifices precisely the latency the engineering effort was meant to recover.
5.10 A defensible benchmark framework
An infrastructure whitepaper should not manufacture benchmark numbers. The correct benchmark injects timestamps at each stage:
t0 = first byte/event observable t1 = application receives complete message t2 = decode complete t3 = state update complete t4 = strategy decision complete t5 = transaction built t6 = signature complete t7 = first outbound byte t8 = relay acknowledgment t9 = transaction observed processed
Then calculate per-stage durations:
T_ingest = t1 - t0 T_decode = t2 - t1 T_strategy = t4 - t3 T_build+sign = t6 - t4 T_egress-client = t7 - t6 T_relay = t8 - t7 T_landing = t9 - t7
Report distributions, not averages, and correlate them with host and network state:
Report: Correlate with:
p50 CPU utilization
p90 CPU frequency
p95 context switches
p99 run-queue length
p99.9 NIC RX/TX drops
max TCP retransmissions
UDP drops
gRPC queue depth
allocator statistics
event rate
slot
leader region
An illustrative design budget, not a measured NoLimitNodes claim, might target:
The critical insight is that a 50ms system cannot contain a routine 20ms parser, a 10ms polling interval, a cold TLS connection and a synchronous blockhash request. There is no remaining budget.
5.11 Infrastructure comparison
The self-hosted option can theoretically outperform any managed provider if a firm is willing to run enough validators, custom plugins, peering, shred relays and geographic infrastructure. The tradeoff is that the quant team becomes an infrastructure operator.
NoLimitNodes’ value proposition is to move those generic infrastructure costs out of the alpha-development organization while preserving access to low-level Solana primitives. If you are weighing the self-hosted route, start with our 2026 hardware requirements guide.
06Production checklist and conclusion#
6.1 Host and kernel
A sub-50ms architecture should begin with the host scheduler, not the Rust source code.
CPU
- Use a modern high-frequency CPU.
- Pin critical strategy and networking threads to dedicated physical cores.
- Keep hyperthread siblings of critical cores free from noisy workloads where possible.
- Pin high-volume parser/deshred workers separately from strategy workers.
- Consider Linux CPU isolation with
isolcpus,nohz_fullandrcu_nocbsafter testing. - Disable deep power-saving behavior if it produces unacceptable wake latency.
- Monitor actual frequency rather than assuming advertised boost clocks.
- Keep logging, compression, databases and observability agents off the critical cores.
NUMA
On multi-socket systems, keep the NIC, its RX queues and every hot worker on the same node:
NIC
|
+--> NUMA node 0
|
+--> RX queues
+--> stream workers
+--> strategy
+--> signer
Do not receive packets on NUMA node 0 and repeatedly access memory allocated on NUMA node 1. Use CPU and memory affinity deliberately.
Memory
- Preallocate hot data structures.
- Avoid unbounded hash maps.
- Reuse buffers.
- Reserve collection capacity.
- Avoid cloning large protobuf messages.
- Prefer integer identifiers or fixed-size public keys to repeated heap strings internally.
- Benchmark the allocator if allocation remains material.
- Never allow swap-induced stalls on a latency-sensitive host.
6.2 NIC and IRQ configuration
Networking must be measured at the packet level.
- 10/25GbE or better where the upstream environment supports it.
- Place NIC interrupts on controlled CPUs.
- Tune RSS queue count to workload.
- Validate RPS/XPS rather than enabling them blindly.
- Avoid IRQ processing on strategy cores.
- Examine interrupt moderation; excessive coalescing improves throughput while hurting latency.
- Increase socket receive buffers where raw-shred bursts demand it.
- Monitor
SO_RXQ_OVFLand kernel UDP-drop indicators. - Track NIC ring drops.
- Use
ethtool -Srather than relying solely on application metrics. - Consider PTP or hardware timestamping for rigorous latency experiments.
- Benchmark GRO/LRO/offload settings rather than following generic “disable everything” advice.
A tuning change that improves p50 while worsening p99.9 is not automatically an improvement.
6.3 gRPC and TCP
For Yellowstone and parsed streams:
- establish channels during startup and keep them warm
- respond correctly to keepalive/ping behavior
- enable
TCP_NODELAY - avoid reconnecting to change filters when the protocol supports bidirectional updates
- use multiple independent connections only when they provide actual redundancy or partitioning
- bound message queues
- monitor last-received slot and message timestamp
- detect silent stale connections
- implement exponential reconnect backoff outside the hot loop
- use replay/from-slot support where semantically appropriate
- deduplicate after reconnect
NoLimitNodes Yellowstone currently documents server ping behavior and bidirectional filter updates (gRPC docs).
6.4 TLS and QUIC
TLS handshakes should be control-plane events, not order-path events.
- keep HTTP/2 channels persistent
- preserve connection pools
- use TLS 1.3-capable stacks
- permit session resumption where supported
- pre-resolve critical hostnames where operationally appropriate
- monitor connection age and reconnect rates
- never create a new HTTP client per transaction
For QUIC:
- open the connection during process initialization
- keep it alive and reuse it
- open lightweight streams per transaction
- detect path migration or endpoint changes
- retain enough fallback capacity to use HTTPS/RPC if QUIC becomes unhealthy
6.5 Solana-specific execution state
Maintain asynchronously:
- recent blockhash
- current slot
- leader information where used
- priority-fee observations
- account state required by the strategy
- address lookup tables
- token-account derivations
- program account metadata
Do not discover these when the opportunity has already arrived. A latency engine should resemble:
continuously refreshed
control state
|
v
SIGNAL ---> mostly-complete transaction template
|
+--> patch dynamic fields
+--> sign
+--> send
not:
SIGNAL | +--> query blockhash +--> query accounts +--> find ATA +--> load IDL +--> compute instruction +--> simulate +--> sign +--> connect +--> send
The second architecture cannot reliably be described as HFT infrastructure.
6.6 Fork and bank correctness
Latency does not justify corrupted state. For processed data:
- accept that observations may belong to forks
- tag state by slot and bank where supported
- distinguish tentative from confirmed state
- implement rollback
- do not combine updates from two providers based solely on
bank_id
With Agave 4.3-era streaming, bank_id must increasingly become part of the state key. Solana’s Alpenglow migration documentation explicitly warns that multiple banks can exist within a slot and that bank_id is local to each connection/provider (solana.com).
The low-latency system that reacts fastest to incorrect fork state can lose faster than everyone else.
6.7 Observability
Record timestamps without blocking the hot path. At minimum:
stream_receive_ns decode_complete_ns strategy_complete_ns sign_complete_ns send_start_ns relay_ack_ns processed_observed_ns confirmed_observed_ns finalized_observed_ns
Export metrics from another thread. The critical dashboard should contain:
- reaction p50/p95/p99/p99.9
- decode, strategy, and sign latency
- send-to-ack and send-to-processed latency
- reconnects and dropped events
- queue depth and stale-slot distance
- shred packet loss and deshred reconstruction failures
- CPU run-queue and NIC drops
- transaction landing rate and failure reason
- priority fee
- leader/region
Without these measurements, “low latency” is marketing rather than engineering.
6.8 Final production checklist
Before calling an engine sub-50ms, verify:
- Yellowstone/Program Streams connections are established before trading begins.
- No DNS lookup occurs on a signal path.
- No TLS or QUIC handshake occurs on a normal order path.
- No synchronous
getLatestBlockhashoccurs after signal detection. - No IDL is loaded at runtime on the hot path.
- No generic Borsh decoder processes data the strategy could receive pre-parsed.
- Protobuf is used for high-volume semantic feeds.
- Raw shreds are processed through bounded buffers.
- UDP packet loss is observable.
- Strategy queues are bounded.
- Critical cores are isolated from background work.
- NIC IRQ placement is validated.
- NUMA placement is understood.
- Transaction templates are prepared ahead of time.
- Signing keys never appear in application logs.
- UltraSend credentials are stored in a secrets manager.
- A signed transaction is serialized once.
- Ambiguous retries reuse the exact same bytes.
- Relay acknowledgment is not confused with landing.
- Landing is independently verified.
- Processed state can roll back.
(slot, bank_id)semantics are supported for newer Geyser streams.- Multi-provider feeds reconcile on block identity, not local bank IDs.
- Every latency component exports p99 and p99.9.
- Load tests include burst traffic rather than constant synthetic rates.
- Failover paths are continuously exercised.
- Parser/schema upgrades have compatibility tests.
- Strategy behavior under stale data is explicitly defined.
Conclusion#
Solana HFT has progressed beyond the stage where “use a fast RPC” is a sufficient infrastructure strategy. The competitive unit is the complete execution pipeline.
A system can receive data from a fast provider and still be slow because it spends 15ms parsing JSON. It can decode instantly and still be slow because it synchronously requests a blockhash. It can build a transaction in microseconds and still lose because it opens a new connection for every order. It can receive shreds before competitors and still trade incorrectly because it ignores forks. It can optimize median latency while silently accumulating hundreds of milliseconds of queue delay under bursts.
The engineering objective is therefore:
Not merely:
min T_RPC
But:
min ( T_observation + T_decode + T_state + T_decision
+ T_build + T_sign + T_egress )
subject to:
correctness, availability, fork safety, risk limits
That architecture naturally separates into three NoLimitNodes data planes.
- Raw Shredstream moves observation toward the earliest available ledger-data boundary.
- Yellowstone gRPC exposes low-level validator state through efficient, filtered, strongly typed streams.
- Enhanced and Program Streams eliminate undifferentiated client-side protocol-decoding work for protocols such as Pump.fun, Raydium, Orca and Meteora.
On the opposite side of the engine, UltraSend provides an outbound persistent HTTPS/QUIC path for already-signed transactions. Its existence also emphasizes an important systems principle: ingest and egress should each use the protocol best suited to their job rather than forcing the entire execution stack through generic JSON-RPC (UltraSend overview).
The future will tighten these requirements further. Solana is shortening its timing envelope, and Alpenglow reduces finality dramatically while introducing new streaming correctness requirements around multiple banks per slot. The faster the network becomes, the less room remains for avoidable client-side overhead.
In that environment, the advantage is unlikely to belong merely to the firm with the shortest piece of strategy code. It belongs to the firm whose infrastructure treats every allocation, queue, parser, connection, syscall, network hop and state transition as part of the execution algorithm.
That is the sub-50ms edge.
Sources and further reading#
- Solana Foundation: Alpenglow upgrade and Geyser consumer guidance
- Jito: ShredStream low-latency transaction feed documentation
- Anchor 0.31 release notes: custom discriminators
- NoLimitNodes: Yellowstone gRPC overview
- NoLimitNodes: Program Streams overview
- NoLimitNodes: Program Streams payload formats
- NoLimitNodes: UltraSend overview
- NoLimitNodes: authentication matrix
Every benchmark in this blog runs against our public endpoints.
Spin up an RPC, WebSocket, or gRPC endpoint in under a minute. Flat pricing, no request caps. Reproduce the numbers for your own workload.