ByAUJay
What Kind of Throughput Benchmarks Should I Expect From Leading Batch Verification SDKs Validating Thousands of Proofs Per Block?
Decision-Makers
This post takes a closer look at block-level capacity and SDK-level microbenchmarks, breaking them down into real, usable throughput figures that you can actually budget for on Ethereum and EVM L2s. We’ll cover solid numbers, up-and-coming practices, and some common pitfalls to steer clear of. If you're in a position where you need to validate hundreds or even thousands of proofs per block, we've got the scoop on what's doable right now, along with some tips on how to make things even better down the line.
TL;DR (description)
- When it comes to Ethereum, if you're just verifying Groth16 proofs in a straightforward way, you're looking at around 150 to 225 proofs per 45M-gas block. But when you bring in aggregation or recursion, you can squash thousands of proofs down to a single verification that runs at about 200 to 300k gas. If you check out some of the SDKs and libraries like arkworks and gnark-crypto, you'll see they can handle hundreds to thousands of verifications per second off-chain. Plus, there are specialized verification layers like Aligned and zkVerify that are already cranking out more than 1,000 proofs per second. (theblock.co)
1) The on‑chain ceiling you’re budgeting against
Before diving into SDK throughput, let's take a moment to refresh your understanding of what really goes into an Ethereum block.
- Current L1 block gas budget: Back in July 2025, Ethereum validators decided to bump the block gas limit up to 45 million, an increase from around 36 million earlier that same year. So, that gives you a rough idea of your “per 12 seconds” computing space on the mainnet right now. (theblock.co)
- Pairing precompiles and costs (L1):
- BN254 pairing (alt_bn128): This one comes in at 34,000·k + 45,000 gas (thanks to EIP‑1108). A lot of Groth16 L1 verifiers lean towards BN254 since it’s already precompiled. Check it out here.
- BLS12‑381 precompiles (EIP‑2537) made their debut with Pectra on May 7, 2025. The cost for a pairing check is 32,600·k + 37,700 gas. This is now live on the mainnet, right alongside KZG’s point-evaluation precompile from EIP‑4844. More details here.
- KZG point evaluation precompile (EIP‑4844, 0x0A): This one has a straightforward fee of a fixed 50,000 gas per verification. You can learn more about it here.
What This Means for Raw Per-Block Proof Counts (Rule-of-Thumb):
So, here’s the deal with raw per-block proof counts:
- So, when it comes to Groth16 on BN254, you're looking at a typical verifier costing around 200-230k gas, depending on the public inputs. If we do a little math, that's about 45,000,000 gas divided by 220,000, giving us roughly 200 proofs per block, and that’s not even factoring in calldata and all the other extra costs. According to Horizen Labs, they’ve broken it down to about 207,700 gas as a fixed cost, plus around 7,160 for each public input, which definitely aligns with what we've seen in practice. You can check out more details here.
- BLS signatures verify (usually with 2 pairings): 37,700 + 2×32,600 = 102,900 gas, which means about ~437 verifications for every 45M-gas block, not counting calldata and logic. The cool thing about aggregating BLS signatures is that it keeps this number steady, even as more signers come on board. (eips.ethereum.org)
- KZG (EIP‑4844) point checks (50k each): So, the maximum theoretical limit is roughly 900 per block, not taking into account calldata and app logic. (eips.ethereum.org)
Takeaway: When it comes to L1, getting to “thousands per block” means you need to either condense a bunch of proofs into a single verification (think aggregation or recursion) or move the verification off-chain to a specialized layer and then just attest on-chain.
2) What off‑chain batch verification SDKs actually deliver (CPU throughput you can trust)
Diving into the technical details, the main hang-ups in proof verification are all about pairings and those small multi-scalar multiplications (MSMs). Luckily, some solid libraries that work on today’s CPUs can manage pairings in under a millisecond. What does that mean? Well, it translates to hundreds of Groth16 verifications happening every second per core, and that’s even before we factor in any batching tweaks!
- Here are the real pairing timings (BN254) from a cross-library benchmark:
- gnark‑crypto: full pairing takes about 0.589 ms (with the Miller loop at 0.2795 ms and final exponentiation at 0.3094 ms).
- herumi/mcl: clocks in around 0.609 ms.
- Other libraries fall within the range of 0.90-1.47 ms. You can check out the details here.
- Just a quick back-of-the-envelope calculation based on those timings:
- A Groth16 verification requires 3 pairings along with some light multi-scalar multiplication (MSM) and field operations. So, we’re looking at a baseline of about 3 × 0.589, which rounds up to around 1.77 ms. That gives you roughly 565 verifications per second on a single core before considering any overheads. If you're working on a 16-core server, you can expect around 5,000 to 8,000 verifications per second. This aligns pretty well with what we've seen in real-world applications, assuming memory and I/O aren’t the limiting factors. (These numbers are based on gnark-crypto’s pairing timings; the calculations are all ours.) (hackmd.io)
- Why real batch verification speeds you up:
- So, batch verification is pretty cool because it combines the Miller loops from multiple proofs and only requires one final exponentiation. This can save you around 40-50% of time when working with large batches. If you take a look at the gnark‑bench breakdown we discussed earlier, the math shows that you get pretty close to (Miller share)/(Miller+FinalExp) ≈ 0.2795 / 0.589, which boils down to about 47% of the cost compared to checking them one by one. You can find that Arkworks makes this super clear with its groth16::batch APIs. Honestly, if you're dealing with big batches on a single machine, you can expect roughly a 2× improvement in wall-clock time, plus you’ll benefit from multi-core parallelization. Check it out here: (hackmd.io)
- Library/SDK notes:
- arkworks (Rust): This one's a solid choice if you're looking for a production-grade Groth16 verifier. It comes with a documented batch API, making it a great fit for Rust services that need to handle tons of proofs per second. Check it out here.
- gnark + gnark-crypto (Go): If speed is key, you'll appreciate the fast pairings and MSM here. They offer straight-through verifiers and even a Solidity exporter for BN254 Groth16. Plus, there are GPU acceleration hooks for provers, although you don't actually need them for verification. Dive into the details here.
- Important reminder: Be cautious about any ad-hoc protocol “extensions.” There are reports from Zellic about vulnerabilities in a non-standard Groth16 extension used for batch flows until they got patched, so it's best to stick to upstream, audited code paths. Learn more about it here.
3) Aggregation and recursion are how you scale to “thousands per block”
Batch verification is what really speeds up off-chain services. On the other hand, when it comes to on-chain processes, you need to condense everything into a single, cost-effective check.
- SnarkPack (Groth16 aggregation): This nifty tool lets you bundle together 8,192 proofs in just 8.7 seconds, and it can verify the whole bundle in only 163 milliseconds, all on regular hardware. Both the verifier and proof sizes scale as O(log n). It’s basically the easiest way to pack a ton of Groth16s into a single verifier call for each block. Check it out here: eprint.iacr.org
- STARK/PLONK families: These use recursion to bundle multiple leaf proofs into a single SNARK, which is then verified on-chain. Nowadays, there are some pretty cool verifiers ready to go:
- Succinct SP1 zkVM: This one does EVM verification, and it costs about 275-300k gas for each wrapped proof. It’s already live on Ethereum and major L2s. You can check it out here.
- RISC Zero (Bonsai): This is the STARK to SNARK wrap that’s been getting some solid reports; on-chain verification is around 245k-300k gas in actual deployments. More details can be found here.
- KZG World after 4844: when you're checking “is this KZG commitment consistent with value y at point z,” each evaluation costs you a steady 50k gas. So, you have two options:
- You can directly verify up to about 900 evaluations per block, or
- You can SNARK-wrap the batch and pay around 200-300k just once (which is usually a better deal when you’re bundling a bunch of logical checks and app logic). (eips.ethereum.org)
- BLS12‑381 is now live on L1 since Pectra, which is great news for KZG‑ish workflows and BLS signature aggregation. To give you a sense of the numbers, a 2-pairing check on BLS12‑381 is about ~102,900 gas, while for BN254 it's around ~113,000, but BLS12‑381 offers better security margins. We're planning to make BLS12‑381 the go-to for new on-chain verification processes unless some specific proof system really needs BN254. Just a heads-up: even though BLS12‑381 is operational on L1, Groth16 over BLS12‑381 isn't the best choice. Groth16 has some field requirements that usually lead folks to prefer BN254, BLS12‑377, or BW6‑761. (eips.ethereum.org)
4) Concrete “proofs per block” scenarios you can explain to finance
When you're setting OKRs or drafting the PRD, keep these in mind:
- Scenario A -- Naïve Groth16 on L1 (no aggregation):
- We're looking at around 220k gas for each proof, which means in a 45M-gas block, we could theoretically fit about 200 proofs in a best-case scenario. But keep in mind, if there’s any significant calldata or app logic involved, that number could drop. So, if anyone is wondering whether we can pull off “1,000 proofs per block on L1,” the short answer is “not without some aggregation or recursion.” (theblock.co)
- Scenario B -- Aggregated Groth16 (SnarkPack) on L1:
- Off‑chain: We can aggregate up to 5,000 proofs! According to SnarkPack benchmarks, the verification time is around O(log n), and the numbers show that going from 8,192 to just 163 ms for verification is pretty impressive.
- On‑chain: A single Groth16 verification will set you back approximately 200-250k gas. The awesome part? You can handle “thousands per block” with just one transaction. So, your main time commitment lies in the off‑chain aggregation, which takes just a few seconds. Check out more details here.
- Scenario C -- BLS signature aggregation (committees/oracles):
- Here, we aggregate off-chain into a single signature and then verify it on-chain using 2 pairings, which costs about ~102,900 gas. The cool thing is that scaling the number of signers from 10 to 10,000 doesn’t affect the on-chain verification cost; the only thing that changes is the calldata for the message/metadata. You can read more about it here.
- Scenario D -- KZG point evaluations (post‑4844):
- If you really need separate on-chain evaluations, you're looking at around 900 checks per block, with each costing about 50k gas. Otherwise, you might want to SNARK-wrap the whole batch, which would run you about 200-300k gas to verify. (eips.ethereum.org)
- Scenario E -- zkVM Receipts (SP1 / RISC0):
- Each wrapped receipt uses about 275-300k gas. You can combine multiple leaf proofs into a single receipt through recursion.
- It’s better to aim for one verification per batch for each block (or across a few blocks) instead of doing a ton of separate verifications. (succinct.xyz)
5) SDK‑level, system‑level, and chain‑level knobs that change your throughput by 10×+
Practical Levers We Use to Help Clients Go from "Hundreds" to "Thousands"
When it comes to helping our clients scale up, we rely on a few key strategies to make that jump from “hundreds” to “thousands.” Here’s a rundown of what we do:
1. Tailored Marketing Strategies
We dive deep into understanding your audience. By customizing marketing strategies that speak directly to your target customers, we can boost engagement and conversions.
2. Optimized User Experience
Improving the user experience on your website is crucial. We work on making navigation seamless and ensuring that your customers can find what they need without any hassle. A simple tweak can turn casual visitors into loyal customers.
3. Enhanced Social Media Presence
We leverage social media to build strong connections with your audience. By creating engaging content and using targeted ads, we can significantly increase your visibility and reach.
4. Strategic Partnerships
Collaboration is key. We help you identify and establish partnerships that can expand your network and open up new opportunities for growth.
5. Data-Driven Decisions
We believe in the power of data. Our team analyzes performance metrics continually to refine strategies and maximize results.
6. Scalable Systems
It’s all about efficiency. We implement systems and processes that allow your business to scale without losing quality or speed.
7. Continuous Learning & Adaptation
The market evolves, and so should your strategies. We emphasize staying up-to-date with the latest trends and adapting our approaches to ensure ongoing success.
By putting these practical levers into action, we can help you transition smoothly from “hundreds” to “thousands” and set you up for sustained growth. Let's make it happen!
- Try to keep public inputs small. The gas cost for verification increases with each public input--think around +~7,160 gas per input if you’re using a typical Groth16 verifier setup. It’s a good idea to shove as much data as you can into commitments and keep on-chain public I/O to a bare minimum. (medium.com)
- It’s a good idea to stick with batch APIs and multi‑pairing when you’re working internally.
- Using arkworks’
groth16::batchand gnark‑crypto multi‑pairing can save you around 40-50% on large batches. This happens because you only pay for one final exponentiation across the entire batch. So, make sure to base your performance goals on the timing data from pairing, rather than just focusing on the overall end‑to‑end “verify()” microbenchmarks. Check it out here: (docs.rs)
- Using arkworks’
- Let's stick with BLS12‑381 for any new on-chain cryptography on L1.
- After the Pectra update, we now have BLS12‑381 precompiles ready for MSMs and pairings. Good news--pairing gas for BLS12‑381 is a bit cheaper than BN254, and it provides around ~128-bit security compared to ~80-bit for BN254. So, go ahead and use BLS12‑381 for signatures and KZG-related verification processes. Meanwhile, keep using Groth16 on BN254/BLS12‑377/BW6‑761 where it makes sense. Check out more on this here.
- Consider using recursion trees for streaming workloads, and for those cases with “many independent leaf proofs,” SnarkPack-style aggregation is a solid choice.
- With recursion, you can maintain steady on-chain costs per batch and swap latency for bigger batch sizes. On the other hand, aggregation shines when your leaf statements vary and you’re aiming for O(log n) verification. Check it out here: (eprint.iacr.org)
- If you’re aiming for that sweet spot of 1k-10k proofs per second, you might want to explore specialized verification layers.
- Aligned (EigenLayer AVS) is already hitting over 1,000 proofs per second in fast mode and is shooting for about ~40k gas per proof at decent batch sizes when submitting results to Ethereum. On the other hand, zkVerify (Substrate L1) has smashed through 1M+ testnet verifications and backs up Groth16/PLONK/SP1/RISC0/Plonky2. These options really help slash your on-chain verification costs and take the pressure off the EVM’s throughput limits. (blog.alignedlayer.com)
- Make sure to check if your library choices stack up with some real pairings/MSM microbenchmarks.
- Both gnark‑crypto and herumi/mcl perform really well on BN254; you can expect per-pairing timings to fall in that sweet spot of 0.6-0.9 ms, which is a solid baseline to keep in mind for capacity planning. (hackmd.io)
- Avoid making assumptions about precompile gas across different chains.
- Keep in mind that EIP‑1108 costs are specific to Ethereum; not all L2s or L3s follow the same rules. If you hardcode the gas costs for pairing precompiles, you might run into a denial of service since some chains have different pricing (like the historical variations seen with zkSync). It’s best to fetch or set values that are specific to each chain. (infsec.io)
- Security hygiene for batch flows.
- Avoid mixing protocol variants on the fly. Audit reports have uncovered some tricky bugs in non-standard Groth16 “extensions” that are used in batched verifiers. It’s best to stick to upstream primitives or aggregators that have been thoroughly reviewed. (zellic.io)
6) Worked numbers you can drop into your spreadsheet
- Off‑chain batch verification capacity (using one 16‑core CPU VM):
- Starting at about 0.589 ms for each pairing, you can expect roughly 565 Groth16 verifications per second per core. That adds up to around 9,000 verifications per second across all 16 cores before batching comes into play. With batch multi‑pairing, you can usually see a 2× speed increase, bringing you to about 18k verifications per second. Keep in mind that this is compute-bound and assumes you have hot caches, pinned cores, and sensible memory settings. (We figured these numbers out using gnark’s pairing timings, but it's a good idea to validate on your own hardware.) (hackmd.io)
- L1 “how many proofs per block” sanity checks at 45M gas:
- For Groth16 BN254 with 2 public inputs, we're looking at around 220k gas, which means we can fit about 204 proofs in a block without any aggregation. (theblock.co)
- When it comes to BLS aggregate signature verification, that runs about 103k gas, allowing for around 437 verifies per block. (eips.ethereum.org)
- For KZG point evaluations (4844), it's about 50k gas, translating to roughly 900 checks per block. (eips.ethereum.org)
- Lastly, if we look at aggregated/recursive SNARKs (like SP1 receipts), that's around 275-300k gas, which means we can handle “one per batch per block.” Just a heads up though: the batch size is really dictated by how fast we can do off‑chain aggregation, not what's happening on-chain with gas. (succinct.xyz)
- Let's talk about aggregating tons of Groth16s using SnarkPack:
- We managed to aggregate 8,192 proofs in just 8.7 seconds, and verifying that aggregate took only 163 milliseconds. So if you're looking at 5,000 proofs, you're looking at about ~5.3 seconds for aggregation on a similar setup; the on-chain gas cost is roughly equivalent to a single Groth16 verification. (eprint.iacr.org)
7) Emerging best practices we’re deploying in 2026
- Let’s use BLS12‑381 across the board on L1. Pectra’s EIP‑2537 is a game changer - it cuts down gas costs for pairs and opens up native MSM/pairing precompiles. We should make sure our new verifiers and signature schemes are in sync with that. For anything that requires it, we can stick with Groth16 on BN254 or consider other cycle-friendly pairs like BLS12‑377 or BW6‑761. Check it out for more details: (blog.ethereum.org)
- Avoid paying for the final exponentiation N times. If your SDK has options for multi-pairing or batch verification, definitely take advantage of them; it can boost your throughput by 1.5 to 2 times in the verifier's hot path. (hackmd.io)
- Reduce the size of public inputs; store larger data in commitments. On EVM, public inputs often lead to gas inefficiencies for many verifiers. Utilizing Pedersen, Merkle, and KZG can help keep on-chain I/O minimal. (medium.com)
- Pick aggregation or recursion based on what you’re dealing with:
- For proofing various statements (a bit mixed up): SnarkPack-style aggregation is the way to go.
- For ongoing data streams (like rollups and oracles): recursion trees can help reduce latency and spread out the costs. Check out more details here: (eprint.iacr.org)
- If you need high throughput and can compromise a bit on L1 minimalism, think about checking out some external verification layers:
- Options like Aligned (which can handle over 1,000 proofs per second in fast mode) and zkVerify (supports multiple provers and can manage over 1 million testnet proofs) are solid choices right now. You’ll end up posting concise attestations to Ethereum. Just keep in mind you'll need to budget some time for integration, but you can expect to see huge improvements in cost and throughput. (blog.alignedlayer.com)
- Keep an eye on your assumptions as Ethereum continues to evolve:
- The block gas limit jumped from about 36M to 45M in 2025, and we might see more changes ahead. EIPs like 4844 and 2537 could significantly alter the economics for verifiers. So, make sure to re-evaluate capacity whenever there’s a shift in core protocol parameters or fee markets. (theblock.co)
8) Quick implementation checklist (copy/paste for your JIRA)
- Architecture
- First up, decide between aggregation methods like SnarkPack or aPlonk, and recursion options such as Halo2‑KZG or zkVM receipts.
- Aim for BLS12‑381 precompiles for any new on-chain cryptography you want to work with, but don’t ditch Groth16 on BN254/BLS12‑377/BW6 just yet if you still need it. (blog.ethereum.org)
- SDKs
- For Rust, check out arkworks groth16::batch for batch verification; remember to profile with the release setup and CPU affinity. (docs.rs)
- If you’re working in Go, use gnark/gnark‑crypto. Keep things simple by sticking to upstream verifiers and exporters, and try to avoid any non-standard extensions. (docs.gnark.consensys.io)
- Capacity planning
- Start with 0.59 ms per pairing (BN254) and scale it up based on how many pairings or proofs you’re working with. You can factor in about a 2× boost for larger batch multi-pairing. Just make sure to validate this on your own hardware. (hackmd.io)
- For on-chain SKUs, figure out your per-block throughput based on current gas rates: Groth16 sits around 200 per block; BLS verification is about 400 per block; KZG evaluation is roughly 900 per block; and for recursion/aggregation, expect about 1 per batch. (theblock.co)
- Safety
- It’s super important to pin your library versions and have audit reports handy; steer clear of any DIY Groth16 tweaks. (zellic.io)
- Stretch goals
- If you’re aiming for a sustained output of over 1,000 proofs per second and want to lower your gas/verify costs, consider looking into specialized verification layers like Aligned or zkVerify. (blog.alignedlayer.com)
9) One realistic end‑to‑end example
Goal: Validate 5,000 user-generated Groth16 proofs every 12 to 24 seconds using an Ethereum L1 attestation.
- Off‑chain:
- So, the first step is to accept proofs into a queue and then verify them locally using the Arkworks batch API while also aggregating with SnarkPack.
- With pairing sitting around 0.589 ms and using batch multi‑pairing, a sweet 16‑core node can easily verify over 10k proofs per second. SnarkPack does a fantastic job of aggregating the last 5,000 proofs into one single aggregate in about 5-6 seconds on a well-tuned setup (just for reference, 8,192 took around 8.7 seconds in published benchmarks). (hackmd.io)
- On‑chain:
- When it comes to on-chain processing, you’ll want to submit one Groth16 verification for each batch, which typically costs about 200-250k gas. It’s pretty straightforward to fit this into a 45M-gas block along with your app logic. (medium.com)
- Latency budget:
- For the latency budget, think about it like this: you have the batch fill (queue) plus aggregation (measured in seconds) and then one L1 inclusion which averages around 12 seconds. You’re looking at a P50 of under 20 seconds with some headroom to spare. If minimizing latency is more important to you than cutting gas costs, it might be a good idea to go for shallow recursion and post a receipt every block. (succinct.xyz)
10) Final cautions
- Groth16 on BLS12‑381: just don't do it. Stick with BN254/BLS12‑377/BW6‑761 instead; BLS12‑381 doesn't have the right field properties that Groth16 looks for. You can totally use BLS12‑381 for signatures, KZG, and for those SNARKs designed specifically for it, especially now that precompiles are available on mainnet. Check it out here.
- Avoid hardcoding gas constants across different chains. Even if you think you've got the "standard" precompiles down, the costs can vary on some Layer 2s. It's better to probe or set parameters instead. (infsec.io)
- Use upstream verifiers and go for audited aggregation--steer clear of DIY versions in production unless you’ve got a solid proof and an audit backing you up. (zellic.io)
References (selected)
- Gas math and precompiles: We've got some key EIPs to check out: EIP‑1108 (BN254), EIP‑2537 (BLS12‑381), and EIP‑4844 (KZG point evaluation). Plus, mark your calendars for Ethereum Pectra activation on May 7, 2025, and keep an eye on those 45M block gas limit reports. (eips.ethereum.org)
- Pairing performance: Dive into a gnark-led cross-library benchmark featuring herumi/mcl. It's definitely worth a look! (hackmd.io)
- Verifier gas breakdowns: Horizen Labs has put together a solid analysis of Groth16 verifier costs. If you're curious about the numbers, check it out! (medium.com)
- Aggregation/recursion stacks: Take a peek at SnarkPack, SP1, and RISC Zero Bonsai. There's some exciting stuff happening here! (eprint.iacr.org)
- Specialized verification layers: Check out Aligned, which can handle over 1,000 proofs per second in fast mode, and zkVerify, boasting 1M+ testnet verifications with multi-prover support. Pretty impressive! (blog.alignedlayer.com)
If you’re looking for a tailored capacity plan for your circuits and chain mix, we’d love to help out! Just share your proving keys and the actual public input sizes, and we can benchmark together.
Like what you're reading? Let's build together.
Get a free 30-minute consultation with our engineering team.
Related Posts
ByAUJay
Building 'Private Social Networks' with Onchain Keys
Creating Private Social Networks with Onchain Keys
ByAUJay
Tokenizing Intellectual Property for AI Models: A Simple Guide
## How to Tokenize “Intellectual Property” for AI Models ### Summary: A lot of AI teams struggle to show what their models have been trained on or what licenses they comply with. With the EU AI Act set to kick in by 2026 and new publisher standards like RSL 1.0 making things more transparent, it's becoming more crucial than ever to get this right.
ByAUJay
Creating 'Meme-Utility' Hybrids on Solana: A Simple Guide
## How to Create “Meme‑Utility” Hybrids on Solana Dive into this handy guide on how to blend Solana’s Token‑2022 extensions, Actions/Blinks, Jito bundles, and ZK compression. We’ll show you how to launch a meme coin that’s not just fun but also packs a punch with real utility, slashes distribution costs, and gets you a solid go-to-market strategy.

