En développement

Alpenglow

Solana's next consensus protocol delivers sub-second finality

Partager :
View live transition dashboard

juin 2026, par Solana Foundation

~150ms
Target finality, down from 12.8 seconds
99%
Faster finality than TowerBFT
20% + 20%
Malicious plus offline stake tolerated

Alpenglow

Updated September 2026 • Solana Foundation

Alpenglow is Solana's next consensus upgrade. Consensus is how the validators that run Solana agree on the order of transactions and on when a transaction can no longer be reversed. Today that takes about 12.8 seconds. Alpenglow targets roughly 150 milliseconds.

For most people the effect is simple: transactions settle almost immediately, and wallets and apps keep working as they do today. The rest of this page is for developers and operators who need to know what changes underneath.

Under the hood, Solana's current consensus, TowerBFT, has validators vote by sending transactions, and a block is final once enough of those votes have stacked up over 32 slots. Alpenglow replaces that layer entirely. Validators send votes directly to each other and bundle them into certificates, so a block is final after one or two rounds of voting. Execution is untouched: the SVM, transactions, programs, and fees stay the same.

the life of one block, and where Alpenglow changes itleader buildsa blockunchangedpropagationTurbinePhase 2: Rotor, laterexecutionSVMunchangedconsensusTowerBFTPhase 1: Votor, Agave 4.3final12.8s today~150msgreen: replaced by Alpenglow · grey: untouched
Alpenglow replaces how a block is agreed on and, later, how it is spread across the network. How transactions execute does not change.

Alpenglow rolls out in two phases:

  • Votor is Alpenglow's voting protocol. Validators send votes directly to each other instead of as transactions, aggregate them into certificates, and finalize a block in one or two rounds. It ships in Agave 4.3.
  • Rotor replaces Turbine, the protocol that spreads a block's data across the network, with a single relay layer. It is planned for a later release once Votor is adopted, and is not yet scheduled.

The 150ms is how long a transaction takes to become final, not how often blocks are produced. Block time is being cut separately, by reduced slot times, from 400ms to 200ms in stages.

If you build on Solana, transaction execution does not change. Block production, streaming, and finality do:

  • A slot can carry more than one candidate block. Geyser, the validator's streaming interface, now tags every event with the bank it came from.
  • confirmed and finalized become the same thing.
  • Vote transactions are no longer in blocks.
  • Proof of History no longer paces block production, so tick entries leave the shred stream and the Clock sysvar's timestamp gets a new source.

Start with the migration checklist for your role, then the breaking changes in detail. The technical details cover Phase 1: Votor, including slots, blocks, and banks and finality under Votor; Phase 2: Rotor; the community cluster; and the SIMDs.

Expected Mainnet Activation DateQ3 2026, on Anza's v4.3 release schedule
Devnet ActivationQ3 2026
Breaking Change?Yes
Indexing Changes Required?Yes
Feature GateA1pengvuM6JEcyNuTnMqepBKhwHE3N6PmUrdATGawhJS

Current feature gate activation status:

ClusterStatut d'activation
TestnetActive
DevnetActive
MainnetNon activée

Breaking Changes:

If your appWhenWhat you have to do
Streams data through Geyser / gRPCAgave 4.3 adds bank_id; multiple banks per slot become more common in 4.4Stop assuming one block per slot. Buffer per (slot, bank_id) and promote a single bank once it is confirmed. Learn more
Merges streams from more than one providerAs soon as you consume bank_idbank_id is a node-local counter. Reconcile across connections on the blockhash, never on bank_id. Learn more
Reads at the confirmed commitmentNothing at activation; confirmed is removed in a later releaseconfirmed and finalized become the same thing. Move to finalized only after Alpenglow is live. Learn more
Counts or parses transactions in a blockAt activationVote transactions leave the block entirely. Re-baseline any metric that counted them. Learn more
Reads time from ticks in shreds or entriesAt activationPoH is gone, and tick entries go with it. Take block boundaries from block meta and the block footer instead. Learn more
Reads Clock.unix_timestamp in a programAt activationThe timestamp is no longer the stake-weighted median of vote timestamps. Re-check any logic tuned to the old behavior. Learn more

Sending transactions and running onchain programs are not affected. Alpenglow changes consensus, not execution; the SVM, transaction formats, and fee mechanics are untouched.

bank_id arrives a release early on purpose. Agave 4.3 adds the field. Fast leader handoff, which makes multiple banks per slot more common, ships in 4.4, and even then Anza expects it in under 1% of slots. Adopt bank_id in 4.3, while the case is still rare enough that a buffering bug has little impact.

Migration Checklist

For UsersNo action needed.+

Nothing about signing, sending, or approving a transaction changes. Wallets and applications keep working exactly as they do today.

Sub-second finality enables new use cases from the teams you already use, like a seemingly instant confirmation at the point of sale, with no change on your side.

For DevelopersReading and streaming block data changes. Execution does not.+

Alpenglow does not touch the SVM, transaction formats, fees, or the account model. If your application only sends transactions and reads account state, there is nothing to migrate. The changes are in how blocks are produced, streamed, and finalized.

If you stream data through Geyser or gRPC — indexers, explorers, trading infrastructure, block builders (details):

  • If you subscribe to whole blocks through Yellowstone, upgrade to v16.0.0-rc10+solana.4.3.0 and you are done. It buffers for you.
  • Otherwise, regenerate your protobuf stubs from that tag's proto, key your buffers on (slot, bank_id) instead of slot, keep the bank that reaches Confirmed, and drop the rest.

If you maintain a Geyser plugin — RPC providers, custom indexers compiled into the validator (details):

  • Move off the four legacy callbacks. Agave 4.3 deprecates update_account, notify_transaction, notify_entry, and notify_block_metadata, and slates them for removal in the next major release. The replacements carry a bank_id.
  • If you consume entries or deshredded transactions, handle the two new UpdateParent callbacks. They name a bank whose earlier notifications you must discard.
  • If you need Alpenglow consensus metadata such as certificates, opt into notify_block_footer.

If you fan in multiple RPC or gRPC providers for redundancy (details):

  • Run one buffer per connection. bank_id means nothing outside the stream it arrived on.
  • Reconcile across connections on the blockhash and nothing else.
  • Audit any existing merge keyed on (slot, bank_id) across streams. It fails silently.

If you read at the confirmed commitment (details):

  • Nothing breaks on activation day; all three levels keep working as they do today.
  • After Alpenglow is live, point new code at finalized. Do not switch before then: on TowerBFT, finalized still means a 12.8-second wait. Once live, confirmed becomes equivalent to it and is removed in a later release.
  • Re-check any timeout, retry, or UX delay tuned around 12.8-second finality.

If you index blocks or report throughput (details):

  • Re-baseline transaction counts and TPS dashboards. Vote transactions vanish from blocks, so the number drops sharply without any drop in real activity.
  • Replace anything that reads validator participation out of Vote program instructions. It now lives in the block footer's certificates, which reach you through Geyser's footer callback. Yellowstone's gRPC footer message does not forward them yet.

If you read time from the ledger — tick counting in shreds or entries, or Clock.unix_timestamp in a program (details):

  • Stop counting ticks. PoH no longer paces block production, so tick entries leave the shred stream. If you used ticks to judge how far into a slot the leader is (for example, to decide when to start routing to the next leader), keep a local slot clock instead: track the slot cadence as seen from your node and correct for your latency to the leader, rather than timing from first-shred arrival, which lags the real slot start.
  • If a program or indexer depends on how closely Clock.unix_timestamp tracks real time, re-read how it is now set. The leader sets it between the parent's timestamp and the parent's plus twice the elapsed slot duration, so the room for a dishonest leader to run it ahead grows with skipped slots rather than being a fixed number. Reading it needs no code change.

To find out when a cluster has actually migrated (details):

  • Call the new getAgGenesisCert RPC method, or run solana alpenglow-genesis-info. It returns null while the cluster is still on TowerBFT and the Alpenglow genesis certificate once it has migrated.
  • Gate feature detection on that call rather than on a date or a version string; devnet, testnet, and mainnet each flip at their own slot.

Test against the Alpenglow community cluster.

For Validator OperatorsRegister a BLS pubkey, then upgrade to Agave 4.3.+

Anza's own Alpenglow operator changes are the authoritative checklist. In short:

  • Register a BLS pubkey on your vote account if you have not already. The Validator Admission Ticket (SIMD-0357) activated on mainnet July 22, 2026, and operators without a registered BLS pubkey are excluded from the admitted validator set and stop participating in consensus. See BLS Pubkeys and the Validator Admission Ticket.
  • Upgrade to Agave 4.3 on Anza's v4.3 release schedule.
  • Confirm the cluster's consensus state with solana alpenglow-genesis-info (details).
  • Budget for the loss of vote transaction traffic in any capacity planning that assumed it, and expect vote costs to move off the ledger entirely.
  • If you run a hot spare alongside your primary, make sure only one of them is ever active. Accidental double block production is the most common source of equivocation on mainnet today.

Breaking Changes in Detail

Each change below, and how to tell when the switch has happened. The mechanics behind them are in the technical details.

For Streaming ConsumersOne slot can now carry more than one candidate block. Buffer per (slot, bank_id) and keep only the bank that reaches Confirmed.+

Breaking Change: One Slot Can Contain More Than One Bank

A slot can carry more than one candidate block. Inside the validator each candidate is a separate bank (why). Starting with Agave 4.3, every event from Geyser, and from gRPC providers built on it such as Yellowstone, carries a bank_id that says which candidate it belongs to. A pipeline keyed on slot alone fuses two competing candidates into one block and never notices.

slot 412300800— three candidate banks during replaybank_id 7tx 4vJ9…tx 8pQ2…block metaConfirmedbank_id 8tx 4vJ9…tx c1Ld…block metanever confirmedbank_id 9tx 6nT8…tx 8pQ2…block metanever confirmedkey = slotevents from all three banks land in one blockbanks 8 and 9 were never confirmed, but nothing flags themevery pipeline written before Agave 4.3key = (slot, bank_id)three events, all of them from bank_id 7banks 8 and 9 lost the race and are droppedneeds Agave 4.3 on the node you stream from
Before Agave 4.3 there was no bank_id to key on, so a pipeline had only the slot — and quietly produced the block on the left. The events are illustrative; a real slot carries thousands.

What to do:

  1. Upgrade or regenerate. If you subscribe to whole blocks through Yellowstone, upgrade to v16.0.0-rc10+solana.4.3.0 and you are done; the provider does the buffering. Otherwise regenerate your stubs from that tag's proto so bank_id appears on transaction, account, slot, entry, and block-meta updates.
  2. Buffer per (slot, bank_id), never per slot.
  3. Seal a bank only when your buffer matches the executed_transaction_count and entries_count in its block meta and the sysvar account updates you expect have arrived. If they never arrive, you connected in the middle of a block.
  4. Keep the bank that reaches Confirmed and drop whatever you buffered under other bank_id values for that slot. Votor picks the winner; you never arbitrate.

Good to know:

  • At confirmed and finalized, Yellowstone emits each sealed bank in a fixed order: its data, then block meta, then the slot status. At processed there is no ordering guarantee, as before, and you may also see events from a bank the leader later abandons through an UpdateParent marker. That bank never reaches Confirmed. Per-bank_id buffering handles both cases.
  • bank_id is optional on slot and account updates and a plain uint64 everywhere else. It exists only on Geyser and gRPC. JSON-RPC and WebSocket are unchanged.
  • Yellowstone rc9 (September 17, 2026) added the block footer message and rc10 (September 22) pinned the build to Agave 4.3.0. Both are release candidates; watch the releases page for the final v16.0.0.
  • Reference code: Yellowstone's block_reconstruction_v2.rs at the rc10 tag, and yellowstone-block-machine, which packages the same state machine as a library with a runnable example. The doc comments spell out the sealing rules.
For Geyser Plugin AuthorsAgave 4.3 deprecates the legacy callbacks. The replacements carry bank_id, and two new callbacks tell you what to discard.+

Breaking Change: Geyser Callbacks Become Bank-Aware

This section is for anyone who compiles a plugin against the validator's Geyser interface. If you consume Yellowstone or another gRPC provider, the provider's plugin does this work for you, and the streaming section above is what applies.

Agave 4.3 adds bank-aware versions of the data callbacks and deprecates the old ones. The legacy methods still fire in 4.3, but the 4.3.0 changelog slates them for removal in the next major release.

Deprecated in 4.3Use instead
update_accountupdate_account_from_snapshot for accounts loaded at startup, update_account_for_bank for updates during replay
notify_transactionnotify_transaction_for_bank
notify_entrynotify_entry_for_bank
notify_block_metadatanotify_block_metadata_for_bank

update_slot_status stays. update_bank_status joins it for the statuses that belong to one bank: CreatedBank, Processed, Confirmed, and Rooted.

Two callbacks are new rather than replacements:

  • UpdateParent. Under fast leader handoff, a leader can start building on one parent and then switch, emitting an UpdateParent marker that clears the bank it had started. notify_entry_update_parent fires when that happens and names the cleared bank ID. notify_deshred_update_parent does the same for deshredded transactions, ahead of the data set that begins at the marker. Entry notifications can race the callback, so reconcile on the cleared bank ID rather than assuming everything you already hold for that bank is valid. If you buffer per bank_id, this is one buffer drop.
  • Block footer. notify_block_footer delivers the complete versioned Alpenglow footer with its slot and bank ID, ordered relative to entry notifications. It is off by default; return true from block_footer_notifications_enabled to receive it. This is where the certificates described under Finality Under Votor come from.

For reference, Yellowstone's own plugin at v16.0.0-rc10+solana.4.3.0 implements the bank-aware callbacks and the footer callback but not the two UpdateParent callbacks. It relies on per-bank_id buffering and on the fact that only the confirmed bank is ever sealed. Its gRPC footer message, SubscribeUpdateBlockFooter, forwards the slot, bank_id, bank hash, producer time, and user agent, but not the certificates. If you need certificates over gRPC today, that still takes a plugin of your own.

For Anyone Merging Feeds From Several Providersbank_id is a node-local counter. Buffer per connection and reconcile on the blockhash.+

Breaking Change: Merging Streams From Multiple Providers

Latency-sensitive consumers often subscribe to several providers and deduplicate locally, because an update can reach provider A first on one slot and provider B first on the next. bank_id does not help with that merge. Each validator assigns its own counter as it creates banks, so the number means something inside one connection and nothing across connections. Connection A's bank_id = 7 and connection B's bank_id = 7 are almost certainly different banks, and one real bank can be 7 on one connection and 12 on another. It also carries no order: two ids from the same stream only tell you whether they differ.

one slot, two connections, two independently assigned countersconnection Arpc-a.examplebank_id 7blockhash 9xK…d4bank_id 8blockhash 3mB…7aconnection Brpc-b.examplebank_id 12blockhash 9xK…d4bank_id 7blockhash 3mB…7ablockhashes matchone bank, safe to mergebank_ids matchtwo unrelated banksthe only key that crosses connections is the blockhashIt arrives on SubscribeUpdateBlockMeta. Nothing on a transaction orslot-status update is comparable across streams — bank_id least of all.
Both connections are reporting the same two banks for the same slot. Every bank_id disagrees, and one value — 7 — names a different bank on each side.

What to do:

  1. Keep one buffer per connection, keyed on that connection's own (slot, bank_id), and tag each connection so that mixing them is an error your code catches. Feeding two streams into one buffer runs without complaint and hands back blocks fused from unrelated banks.
  2. Reconcile on the blockhash, which arrives in block meta, and only once both sides are sealed. Two unsealed banks both carry an empty blockhash and would compare equal.
  3. If you cannot wait for block meta, treat one stream as authoritative per slot and use the others for liveness only. A merged view that stays correct under forks has to wait for the blockhash.

yellowstone-block-machine handles the per-connection half: out-of-order events, forks, dead slots, and commitment ordering for one stream. Reconciling across connections is still yours to write.

For RPC ConsumersNothing breaks on day one, but confirmed and finalized stop being different states.+

Commitment Levels: Confirmed and Finalized Converge

processed, confirmed, and finalized all still exist under Alpenglow and still mean what they mean today. No code change is required on activation day.

In production almost everyone reads at confirmed, which lands in about one slot, and there has never been a confirmed block that did not finalize. The guarantee was weaker than that record: a confirmed block could in principle still be dropped, and ruling that out meant waiting the 12.8 seconds TowerBFT needed to finalize. Under Alpenglow finality arrives in roughly 150ms, so you can listen for finalized directly and take the stronger guarantee at no cost in latency (how). Once Alpenglow is live, point new code at finalized and migrate the rest; confirmed will be deprecated and removed in a later release. Do not switch before activation: on TowerBFT, finalized still means waiting 12.8 seconds, and your app will wait way too long for finality.

Pre-confirmation streaming is unaffected. Alpenglow does not touch execution, so anything that watches transactions as a block is being built (Geyser processed notifications, Triton's Whirligig-style streams) sees the same data at the same point in the pipeline. The difference starts after voting.

For IndexersVotes stop being transactions, so block contents and transaction counts change.+

Breaking Change: Vote Transactions Leave the Block

Alpenglow validators send votes directly to each other and aggregate them into certificates. Votes are no longer transactions, so they no longer appear in blocks. For anything that reads blocks:

  • Transaction counts and TPS drop sharply. Vote traffic has been a large share of the transactions in a block. Removing it is an accounting change, not a throughput regression, but every dashboard, benchmark, alert threshold, and historical comparison whose baseline included votes needs re-baselining. Benchmarking tools that have not been updated will report the change as a collapse in network activity.
  • Vote filtering becomes a no-op. Pipelines that filter out the Vote program or set Geyser's vote filter keep working; they have nothing left to filter.
  • Validator participation needs a new source. Anything that measures which validators voted, or how, by parsing Vote program instructions out of blocks stops seeing data. That information now lives in the certificates in the Alpenglow block footer: notar_reward_cert and skip_reward_cert each carry an aggregate BLS signature plus the bitmap of the validators it covers (details).
For Anyone Reading Time From the LedgerPoH no longer paces blocks. Ticks leave the shred stream, and the Clock sysvar's timestamp gets a new source.+

Breaking Change: Ticks Leave the Ledger

Today a leader's Proof of History stream emits 64 tick entries per slot, spaced evenly through it, and the tick count in each shred tells anyone watching the stream how far into the slot the leader is. Under Alpenglow, Votor's timeouts and certificates pace block production instead of PoH, so leaders stop emitting ticks. The ledger keeps its slot-level notion of time and loses the sub-slot one.

Who is affected: anyone who read ticks as a finer clock than the slot. The common case is transaction routing. With 200ms slots, a sender that knows it is 100ms away from the current leader, sees the leader's last slot, and sees a shred at tick 32 of 64 can infer there are only 100ms left and start routing to the next leader. That inference has nothing to read after activation. Anything else that treated an entry with no transactions as a tick, or waited for a final tick to consider a block complete, is affected the same way.

What to do instead:

  • For block completeness, use the block footer and block meta's entries_count and executed_transaction_count (details).
  • For time inside a slot, keep your own slot clock. Slots start on a fixed cadence, so track when successive slots begin as seen from your node, correct for your measured one-way latency to the leader (the shreds you see were produced that long ago), and derive slot boundaries from the corrected cadence rather than from the arrival of any single shred. Timing a full slot from first-shred arrival alone is late by production plus propagation delay, which on 200ms slots is a material fraction of the slot. There is no replacement signal in the ledger; the block footer's production time is set once per block, not as the block fills.

The Clock Sysvar Has a New Source

Programs read wall-clock time from Clock.unix_timestamp. Today that value is the stake-weighted median of the timestamps validators attach to their vote transactions. Vote transactions leave the ledger under Alpenglow (why), so that input disappears with them.

Under Alpenglow the leader sets the timestamp for its block directly, within a range that depends on how much slot time has passed since the parent. The lower bound is the parent's timestamp. The upper bound is the parent's timestamp plus twice the elapsed slot duration: for a block directly after its parent on 200ms slots that is parent + 400ms, and if four slots were skipped in between it is parent + 2s. Validators reject a block whose timestamp falls outside that range. The rule is specified in SIMD PR #363; check it before hard-coding any number. The value lands in the block footer for indexers and in the same Clock sysvar programs already read, so no code change is needed to keep reading it.

Who is affected: programs and indexers that depend on how closely the timestamp tracks real time, not on the fact that it exists. The trust model shifts from a stake-weighted median to one leader per block:

  • A dishonest leader can push the clock ahead, but only up to the bound, once, in its own block. It cannot move it backwards. Because the bound scales with elapsed slot time, the room to skew is largest right after a run of skipped slots.
  • Honest leaders correct for that by setting parent + 0 until real time has caught up, so a run of dishonest leaders can accumulate skew and a run of honest ones bleeds it off. Over an honest majority the clock converges on real time.
  • The value stays monotonic, updates once per slot, and remains a coarse clock. There is no fixed drift guarantee to code against; treat the envelope as a function of slot duration and skipped slots, not as a constant. Nothing about Clock.slot, Clock.epoch, or the other fields changes.
For Anyone Tracking the RolloutThe cluster will tell you whether it has migrated. There is a CLI command and an RPC call to get the consensus status.+

Checking Whether Alpenglow Is Active

There is no fixed activation time, and each cluster migrates on its own schedule. Ask the cluster.

Agave v4.3 adds a getAgGenesisCert RPC method that returns Alpenglow's genesis certificate, the certificate covering the first block produced under the new consensus. It takes no parameters and reads from the finalized bank:

  • null: the cluster is still running TowerBFT.
  • A certificate object: the cluster has migrated, and block.slot is the slot where Alpenglow consensus began.
curl https://api.mainnet-beta.solana.com -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"getAgGenesisCert"}'

While the cluster is still on TowerBFT, the result is null:

{ "jsonrpc": "2.0", "result": null, "id": 1 }

Once it has migrated, the result carries the certificate:

  • block.slot and block.blockId: the slot of the first block produced under Alpenglow, and its block ID as a 32-byte array.
  • signature.signature and signature.bitmap: the 192-byte aggregate BLS signature, and the bitmap of the ranks of the validators it covers.

The Solana CLI wraps the same call, from v4.3 onwards:

solana alpenglow-genesis-info

Both ends have to be on 4.3. An older CLI does not have the subcommand, and an RPC node running an earlier version answers getAgGenesisCert with a Method not found error (-32601) rather than with null. Detection code should treat that differently from "still on TowerBFT". Check the two versions with solana --version and solana cluster-version.

Before the migration the command prints still running tower. After it, the epoch the feature gate activated in, the genesis block's slot and block ID, and how many validators signed:

Alpenglow genesis information:
  Feature flag activation: Epoch 987
  Genesis Block - Slot 412300800, Block ID 7Yx3...9Qk2
  Genesis Vote - 1183 validators participated, Signature 8f2a...

@solana/kit exposes it from 8.3.0 onwards, typed and on the default RPC API:

import { createSolanaRpc } from "@solana/kit";

const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const cert = await rpc.getAgGenesisCert().send();

if (cert === null) {
  // The cluster is still running TowerBFT.
} else {
  console.log(`Alpenglow has been active since slot ${cert.block.slot}`);
}

Gate any Alpenglow-specific behavior on this call rather than on a date or a client version string. SDKs other than Kit do not expose the method yet, so elsewhere it is a raw JSON-RPC request for now.

Technical Details

Phase 1: Votor

Votor replaces TowerBFT's voting in Agave 4.3. It tolerates 20% of adversarial stake plus 20% of offline stake while still reaching consensus.

TowerBFT needs a supermajority of greater than two-thirds of stake to achieve a confirmed status. Alpenglow is a marked improvement in terms of the overhead required to finalize a block.

Alpenglow no longer uses vote transactions. Votes are sent directly between validators, and observed votes and certificates are managed in a separate data structure called Pool, informing Votor and stored with Blokstor.

Voting and Certificates

Voting proceeds in two rounds. In the fast path, a block can be finalized after one round if at least 80% of stake votes to notarize it, that is, votes that the block is valid and should be adopted. If that threshold is not reached, the protocol can continue into a second round, where certificates based on 60% stake thresholds determine notarization, finalization, or skipping.

There are five vote messages a validator can make:

  • Notarization - Voting yes
  • Notarization fallback - Voting yes during the second round
  • Skip - Voting skip
  • Skip fallback - Voting skip for second round
  • Final - Voting to finalize the block

As voting happens, validators aggregate votes to one of the following quorum certificates depending on the vote state:

  • Fast finalization - Received >= 80% of stake votes to notarize in first round. Finalize.
  • Notarization - Received only >= 60% to < 80% of stake votes in first round. Ready for second round.
  • Finalization - Received >= 60% of stake votes in the second round. Finalize.
  • Notarization fallback - Received >= 60% of stake votes that either vote notarize or notarize fallback in the second round
  • Skip - >= 60% of stake votes to either skip in the first or second round
every correct node casts exactly one notarization-or-skip vote per slotblock b proposed for slot sfast path — one roundNotarVote(b)≥ 80% of stake notarizesFast-finalization certFINALtwo roundsNotarVote(b)≥ 60% but < 80%Notarization cert — not finalFinalVote round, ≥ 60%Finalization certFINALskipSkipVote(s)≥ 60% of stake skipsSkip certslot is skippedvotes split and nothing clears 60%SafeToNotar / SafeToSkip fires → notar-fallback or skip-fallback vote → Notar-fallback cert at ≥ 60%A fallback vote is a second vote added on top of the one required vote, never a replacement, and only once it is safe to add.
Three routes out of a proposed block, and the certificate each one produces. A node casts exactly one NotarVote or SkipVote per slot; fallback votes are added on top of that one, never in place of it.
Slots, Blocks, and Banks

A slot is a fixed window of network time in which one pre-assigned leader gets an exclusive turn to build. A block is the bundle of transactions that comes out of it. The network is designed to produce exactly one block per slot, and it has done so reliably enough for long enough that much production code treats "slot" and "block" as synonyms. They are not, and Alpenglow makes the difference matter.

A bank is a validator's in-progress state for one candidate block. A slot ends up with more than one candidate bank in two ways: one that exists today, and one that arrives with Agave v4.4.

  • Equivocation. A leader signs two different blocks for the same slot and hands each to part of the network. Every validator that sees both builds a bank for each. On mainnet this has so far only happened by accident, when an operator's primary and hot spare were both live at once. Under Agave v4.3 this is the only way a slot gets two banks.
  • Fast leader handoff, from Agave v4.4. A leader can start building optimistically on a parent it expects to be notarized. If the network votes to skip that parent instead, the leader restarts for the time remaining in its window. The whitepaper describes this as the same block continuing under a new parent; in a validator it produces a new bank, and to Geyser a new bank is a new block.

Neither case is routine. Equivocation is rare today, and fast leader handoff will make a second bank more common but still the exception: Anza expects it in below 1% of slots.

Alpenglow tightens the ceiling on this: no correct node ever needs to store more than seven distinct blocks for a single slot, down from ten under TowerBFT. That is Corollary 50 of the Alpenglow whitepaper. It bounds what a correct node has to keep, not how many blocks the protocol allows to exist.

Two blocks can never both cross the 60% notarization threshold for the same slot, because that would require 120% of the stake to exist. Whichever candidate crosses it wins; the rest are dropped. Downstream, this is what bank_id lets a consumer act on (details).

Finality Under Votor

Under TowerBFT, confirmed meant an optimistic supermajority about one slot out, and finalized meant 12.8 seconds of lockout. Under Votor a block is final once a finalization certificate exists, roughly 150ms after it was proposed, and confirmed and finalized describe the same state. The 150ms is an expectation, not a constant: it was measured against the stake distribution at the time of testing, moves as that distribution changes, and is lower when a block finalizes in one round than in two.

today — TowerBFTprocessedexecutedconfirmed200–400ms, optimisticfinalized12.8swith Alpenglowprocessedexecutedconfirmed = finalized~150ms, irreversibleone state, two names — confirmed goes away in a later releasetwo ways to get there, both invisible from the outsidefast path — 80% notarizeone round60% notarize, then 60% finalizetwo roundsfinalizedWhich path wins depends onnetwork latency and topology,not on the block. A tight 60% canfinish two rounds before aspread-out 80% finishes one.No new status appears between processed and finalized, and no client change is required on activation day.
The levels do not change meaning; the distance between them collapses. processed still means only that the transaction executed in a bank.

Anza did not redefine confirmed as first-round notarization (60% of stake). That would break the guarantee confirmed carries today and would let a client observe finalized before confirmed for the same transaction. processed is unchanged and still means only that the transaction executed in a bank.

Whether a block takes the fast path (80% of stake notarizes in one round) or goes to a second round (60% thresholds) is invisible from the outside. There is no new status between processed and finalized, and which path wins depends on network latency and topology rather than on anything the transaction did. A tightly clustered 60% of stake can complete two rounds before a geographically spread 80% completes one.

Finality can also be observed directly. A leader embeds the most recent finalization certificate it holds in the Alpenglow block footer, which Geyser exposes through notify_block_footer (opt in with block_footer_notifications_enabled()). BlockFooterV1 carries the bank hash, block production time, the producer's user agent, and up to three optional certificates: block_final_cert, plus the notar_reward_cert and skip_reward_cert used for vote rewards. Two caveats:

  • Every certificate field is optional. A footer without one is normal, not an error. The leader including a certificate is a convenience for the read layer and for debugging, not something the protocol depends on.
  • block_final_cert carries its own slot and block_id. They are not necessarily those of the block containing the footer; a leader cannot know its own block is final while building it, so what it embeds is the latest certificate it had at that moment.

Certificates are not privileged information from the leader. Any validator that collects enough votes assembles a certificate itself and broadcasts it, and anyone holding the votes and the validators' BLS public keys can verify one independently.

Phase 2: Rotor

Alpenglow in its next phase is expected to replace Solana Turbine with a new block propagation service called Rotor. It uses the same erasure coding idea and validator stake-adjusted bandwidth from Turbine. Rotor changes the block propagation plan from a tree of nodes to a single relay layer to minimize network latency. The plan is to make this upgrade at a later stage once Votor has already been adopted by the network.

Alpenglow Community Cluster

After running several tests for months, validators and the core development team are testing the new consensus algorithm on a community cluster. This will ensure a smooth migration from the old consensus protocol to the new one. There are already issues that were identified by the initiative and core devs are working to ensure that the network does not experience downtime during the transition.

Test against it through its explorer at ag.validblocks.com. It goes offline regularly, because taking the cluster down and bringing it back is how the TowerBFT to Alpenglow switch itself gets rehearsed. Alpenglow will soon be testable on testnet.

Alpenglow SIMDs

Alpenglow is defined across several SIMDs. The original proposal introduces the new consensus protocol, while the follow-up SIMDs cover migration, vote account changes, fast leader handoff markers, and VAT implementation details.

SIMD-0326Alpenglow Consensus Protocol
SIMD-0337Markers for Alpenglow Fast Leader Handover
SIMD-0357Alpenglow Validator Admission Ticket
SIMD-0384Alpenglow Migration
SIMD-0387BLS Pubkey Management in Vote Account

Shipping timeline: BLS Pubkey Management in Vote Account (SIMD-0387) activated on mainnet July 8, 2026. The Validator Admission Ticket (VAT, SIMD-0357) activated on mainnet July 22, 2026. Validator operators who have not registered a BLS pubkey on-chain are now excluded from the VAT admitted validator set and stop participating in consensus. This admission gating is enforced by the VAT feature gate; it does not turn on Alpenglow consensus itself, which activates separately in Agave 4.3. See BLS Pubkeys and the Validator Admission Ticket for the registration steps and current activation status.

About This Upgrade

Alpenglow is Solana's first major consensus replacement since TowerBFT. It changes how validators vote, how blocks reach finality, and how consensus information is exposed to downstream infrastructure, while leaving transaction execution and the SVM unchanged.

Votor is the first phase of the rollout, replacing vote transactions with direct validator votes and aggregate certificates and reducing finality from roughly 12.8 seconds to a target of around 150ms. Rotor will follow in a later phase to replace Turbine's block propagation mechanism.

For most application developers, the upgrade requires no migration. The main changes affect validators and infrastructure that consumes block, voting, or finality data.

Learn more: Solana Upgrades