You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Time for RPC to serve a transaction submission: receive the HTTP call, proxy to core's submit endpoint, parse and return the result.
This is measurable today: the v2 submission path is essentially the v1 path.
Scope
Measure submission latency across the three transaction profiles, which differ in XDR size (SAC ≈ 1 KB, contract-token/OZ ≈ 1 KB, Soroswap ≈ 2×) — size affects encode/decode if that ever becomes a factor.
Report p50/p99 per profile, with the measurement setup documented (client location, network assumptions — the org-wide assumption is 50 ms client↔RPC RTT, which must be excluded or stated).
Document the methodology alongside the number.
Done when
We have reproducible per-profile numbers with a documented method.
Just for context and an initial ballpark, when I analyze the vegeta-provided latency of the mainnet TPS load test (running on an m6id.4xlarge), I see the following:
Round-trip time of POST /transactions to receiving PENDING, including network latency:
Workload
Mean
SAC
67ms
OZ
59ms
Soroswap
55ms
I know this isn't enough to consider this "done," but it is a known starting point with v1 that we can point to for hand-waving if necessary. We should expect the same results, if not better given that network latency isn't part of this metric, with v2 once that's all wired in given that the submission code and execution path should be nearly identical.
Method. The p99 60 ms submission target decomposes into ~50 ms client↔RPC network RTT plus <10 ms inside the RPC process, so this benchmark measures the in-RPC part and treats the RTT as a constant. Two existing instruments cover it — no new code:
finished JSONRPC request log line — full sendTransaction handler duration, one line per request (joined to the starting JSONRPC request line on req to filter by method). This is the headline distribution.
soroban_rpc_txsub_submission_duration_seconds — the synchronous RPC→Core POST /tx leg alone.
RPC residue (XDR decode, hash, JSONify) = handler mean − core-leg mean. Means only; quantiles do not subtract.
Environment.stellar/quickstart:testing (stellar-rpc v27.1.1) on an m6id.2xlarge. Load = real fee-bumped Soroban transactions from the tx-load-test tool in stellar-rpc-blaster, three profiles: SAC transfer (≈1 KB), OpenZeppelin token transfer (≈1 KB), Soroswap router swap (≈2.6 KB). Standalone network: 10 RPS × 120 s per profile (~1,150 samples each). Testnet: same box, 2 RPS × 60 s (~115 samples each). Every submission was accepted (PENDING); zero poll errors in every run.
Standalone (headline):
Profile
n
p50
p90
p99
max
core-leg mean
RPC residue mean
SAC transfer
1155
1.14 ms
1.30 ms
4.36 ms
11.4 ms
1.03 ms
0.20 ms
OZ transfer
1154
1.10 ms
1.25 ms
3.08 ms
15.4 ms
0.99 ms
0.20 ms
Soroswap swap
1152
1.22 ms
1.39 ms
4.56 ms
13.3 ms
1.07 ms
0.25 ms
Testnet (confirmation):
Profile
n
p50
p90
p99
max
core-leg mean
RPC residue mean
SAC transfer
114
1.16 ms
1.30 ms
4.00 ms
9.2 ms
1.08 ms
0.19 ms
OZ transfer
115
1.12 ms
1.28 ms
1.43 ms
7.5 ms
0.99 ms
0.20 ms
Soroswap swap
114
1.19 ms
1.39 ms
1.99 ms
12.6 ms
1.08 ms
0.24 ms
Findings.
Worst-profile p99 is 4.6 ms — the <10 ms in-RPC slice holds with 2× headroom. Total slice estimate: 50 + 4.6 ≈ 55 ms against the 60 ms target.
The RPC→Core call carries ~80–83 % of the mean and drives the tail (core-leg p99 tracks handler p99 in every profile). RPC's own processing is ~0.2 ms, flat across profiles.
Envelope size barely matters: the ≈2.6 KB Soroswap profile adds ~0.1 ms at p50 over the ≈1 KB profiles.
Standalone ≈ testnet: medians agree within ~2 %, core-leg means within 5 % — the measured path (handler + local core admission) never touches the network. The thinner testnet p99s are sample-size noise at n≈114.
Cross-checks: log-derived means match the soroban_rpc_json_rpc_request_duration_seconds Summary exactly, counts agree across logs, metrics, and the client, and client-observed HTTP RTT (p50 ≈ 2.5 ms) = handler time + the localhost/nginx hop.
Reproduce. Runner + log-harvest scripts: scripts/tx-submission/ in stellar-rpc-blaster (branch tx-submission-harvest). Raw bundles (client NDJSON, RPC log slices, /metrics scrapes, per-profile summary JSONs): gs://rpc-full-history/results/txsub-standalone-20260728/ and gs://rpc-full-history/results/txsub-testnet-20260728/.
Measured on v1 (v27.1.1); the v2 submission path is expected to be equivalent — re-verify when it is final.
Activity
Shaptic commentedon Jul 17, 2026
Just for context and an initial ballpark, when I analyze the vegeta-provided latency of the mainnet TPS load test (running on an
m6id.4xlarge), I see the following:Round-trip time of
POST /transactionsto receivingPENDING, including network latency:I know this isn't enough to consider this "done," but it is a known starting point with v1 that we can point to for hand-waving if necessary. We should expect the same results, if not better given that network latency isn't part of this metric, with v2 once that's all wired in given that the submission code and execution path should be nearly identical.
marwen-abid commentedon Jul 28, 2026
Results: transaction-submission latency measured inside RPC
Method. The p99 60 ms submission target decomposes into ~50 ms client↔RPC network RTT plus <10 ms inside the RPC process, so this benchmark measures the in-RPC part and treats the RTT as a constant. Two existing instruments cover it — no new code:
finished JSONRPC requestlog line — fullsendTransactionhandler duration, one line per request (joined to thestarting JSONRPC requestline onreqto filter by method). This is the headline distribution.soroban_rpc_txsub_submission_duration_seconds— the synchronous RPC→CorePOST /txleg alone.Environment.
stellar/quickstart:testing(stellar-rpc v27.1.1) on an m6id.2xlarge. Load = real fee-bumped Soroban transactions from thetx-load-testtool instellar-rpc-blaster, three profiles: SAC transfer (≈1 KB), OpenZeppelin token transfer (≈1 KB), Soroswap router swap (≈2.6 KB). Standalone network: 10 RPS × 120 s per profile (~1,150 samples each). Testnet: same box, 2 RPS × 60 s (~115 samples each). Every submission was accepted (PENDING); zero poll errors in every run.Standalone (headline):
Testnet (confirmation):
Findings.
soroban_rpc_json_rpc_request_duration_secondsSummary exactly, counts agree across logs, metrics, and the client, and client-observed HTTP RTT (p50 ≈ 2.5 ms) = handler time + the localhost/nginx hop.Reproduce. Runner + log-harvest scripts:
scripts/tx-submission/instellar-rpc-blaster(branchtx-submission-harvest). Raw bundles (client NDJSON, RPC log slices,/metricsscrapes, per-profile summary JSONs):gs://rpc-full-history/results/txsub-standalone-20260728/andgs://rpc-full-history/results/txsub-testnet-20260728/.Measured on v1 (v27.1.1); the v2 submission path is expected to be equivalent — re-verify when it is final.
marwen-abid commentedon Jul 28, 2026
👉 details and graphs https://stellar-experimental.github.io/stellar-rpc-benchmarks/tx-submission.html