> ## Documentation Index
> Fetch the complete documentation index at: https://docs.intention.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Mempool

> How transactions are admitted, held, ordered, and disseminated before consensus commits them to a block.

The mempool is what stands between a signed transaction and a committed block. It decides what is worth holding, in what order a sender's transactions become eligible, which peers hear about a transaction, and what gets dropped when demand exceeds capacity.

For a trading network this is load-bearing rather than incidental. Order and cancel traffic is bursty, sender-concentrated, and latency-sensitive in an asymmetric way: a cancel that arrives late is worse than an order that arrives late. The structures below exist because a single FIFO queue handles none of that well.

## The path in

<div className="dg" data-dg="mempool-admission">
  <div className="dg-c" style={{aspectRatio:"720 / 252"}}>
    <svg className="dg-w" viewBox="0 0 720 252" aria-hidden="true">
      <path className="dg-wire dg--blue" d="M 124.00 145.00 L 145.60 145.00" />

      <path className="dg-head dg--blue" d="M 152.00 145.00 L 145.60 149.40 L 145.60 140.60 Z" />

      <path className="dg-wire dg--orange" d="M 340.00 145.00 L 356.00 145.00 L 356.00 46.00 L 365.60 46.00" />

      <path className="dg-head dg--orange" d="M 372.00 46.00 L 365.60 50.40 L 365.60 41.60 Z" />

      <path className="dg-wire dg--sky" d="M 340.00 145.00 L 365.60 145.00" />

      <path className="dg-head dg--sky" d="M 372.00 145.00 L 365.60 149.40 L 365.60 140.60 Z" />

      <path className="dg-wire dg--sky dg-soft" d="M 541.00 145.00 L 566.40 120.45" />

      <path className="dg-head dg--sky" d="M 571.00 116.00 L 569.46 123.61 L 563.34 117.28 Z" />

      <path className="dg-wire dg--sky dg-soft" d="M 541.00 145.00 L 566.55 171.40" />

      <path className="dg-head dg--sky" d="M 571.00 176.00 L 563.39 174.46 L 569.71 168.34 Z" />
    </svg>

    <div className="dg-b dg--blue" style={{left:"0.0000%",top:"46.8254%",width:"16.6667%",height:"21.4286%"}}><span className="dg-t">Signed transaction</span></div>
    <div className="dg-b dg--yellow" style={{left:"21.6667%",top:"42.8571%",width:"25.0000%",height:"29.3651%"}}><span className="dg-t">Validation</span><span className="dg-s">signature · format · account state · can the sender pay for it</span></div>
    <div className="dg-b dg--orange dg-left" style={{left:"52.2222%",top:"7.9365%",width:"47.7778%",height:"20.6349%"}}><span className="dg-t">Dropped, with a reason returned</span><span className="dg-s">not silently — the submitter is told why</span></div>
    <div className="dg-b dg--sky" style={{left:"52.2222%",top:"46.8254%",width:"22.2222%",height:"21.4286%"}}><span className="dg-t">Transaction store</span></div>
    <div className="dg-b dg--sky" style={{left:"80.0000%",top:"36.5079%",width:"20.0000%",height:"19.0476%"}}><span className="dg-t">Peer broadcast</span></div>
    <div className="dg-b dg--sky" style={{left:"80.0000%",top:"60.3175%",width:"20.0000%",height:"19.0476%"}}><span className="dg-t">Batch formation, then consensus</span></div>
    <div className="dg-free" style={{left:"0.0000%",top:"85.7143%",width:"100.0000%"}}><div className="dg-n">Validation is cheap and local, so the expensive resources downstream are spent only on transactions that could actually execute.</div></div>
    <div className="dg-lbl" style={{left:"49.4444%",top:"36.5079%"}}>rejected</div>
    <div className="dg-lbl" style={{left:"49.4444%",top:"51.9841%"}}>accepted</div>
  </div>
</div>

A transaction is validated before it is ever stored. Validation is cheap and local — signature, format, account state, and whether the sender can pay for what they are asking — and it exists so that the expensive resources downstream are spent only on transactions that could actually execute. A rejection here returns a reason to the submitter rather than silently disappearing.

## How transactions are held

Accepted transactions are not kept as one flat queue. The store maintains several views over the same set, each answering a different question.

<div className="dg" data-dg="mempool-views">
  <div className="dg-c" style={{aspectRatio:"720 / 332"}}>
    <svg className="dg-w" viewBox="0 0 720 332" aria-hidden="true">
      <path className="dg-wire dg-soft" d="M 195.00 148.00 L 245.00 36.00" />

      <path className="dg-wire dg-soft" d="M 195.00 148.00 L 245.00 92.00" />

      <path className="dg-wire dg-soft" d="M 195.00 148.00 L 245.00 148.00" />

      <path className="dg-wire dg-soft" d="M 195.00 148.00 L 245.00 204.00" />

      <path className="dg-wire dg-soft" d="M 195.00 148.00 L 245.00 260.00" />
    </svg>

    <div className="dg-b dg--blue dg-round" style={{left:"0.0000%",top:"31.0241%",width:"26.3889%",height:"27.1084%"}}><span className="dg-t">One set of accepted transactions</span><span className="dg-s">five views over it, not five queues</span></div>
    <div className="dg-b dg--sky" style={{left:"34.7222%",top:"3.0120%",width:"65.2778%",height:"15.6627%"}}><span className="dg-t">Per-account ordering</span><span className="dg-s">For this sender, which transaction is next?</span></div>
    <div className="dg-b dg--sky" style={{left:"34.7222%",top:"19.8795%",width:"65.2778%",height:"15.6627%"}}><span className="dg-t">Priority index</span><span className="dg-s">Across all senders, what should consensus be offered first?</span></div>
    <div className="dg-b dg--sky" style={{left:"34.7222%",top:"36.7470%",width:"65.2778%",height:"15.6627%"}}><span className="dg-t">Expiry index</span><span className="dg-s">What has passed its deadline?</span></div>
    <div className="dg-b dg--sky" style={{left:"34.7222%",top:"53.6145%",width:"65.2778%",height:"15.6627%"}}><span className="dg-t">Timeline index</span><span className="dg-s">What has this peer not heard about yet?</span></div>
    <div className="dg-b dg--yellow" style={{left:"34.7222%",top:"70.4819%",width:"65.2778%",height:"15.6627%"}}><span className="dg-t">Parking lot</span><span className="dg-s">What is well-formed but not yet eligible?</span></div>
    <div className="dg-free" style={{left:"0.0000%",top:"89.1566%",width:"100.0000%"}}><div className="dg-n">The parking lot is where an integration bug becomes visible: a transaction that is valid but not yet next for its sender is parked, not rejected — it becomes eligible the moment the gap in front of it closes.</div></div>
  </div>
</div>

| View                     | Question it answers                                            |
| ------------------------ | -------------------------------------------------------------- |
| **Per-account ordering** | For this sender, which transaction is next?                    |
| **Priority index**       | Across all senders, what should be offered to consensus first? |
| **Expiry index**         | What has passed its deadline and should be removed?            |
| **Timeline index**       | What has this peer not heard about yet?                        |
| **Parking lot**          | What is well-formed but not yet eligible?                      |

The **parking lot** deserves the most attention because it is where a class of integration bug becomes visible. A transaction can be perfectly valid and still not be next in line for its sender — most often because an earlier transaction from the same account has not arrived or has not been committed. Such a transaction is parked rather than rejected: it stays available, and becomes eligible the moment the gap in front of it closes. A client that submits out of order therefore experiences a delay rather than a failure, but a client that never fills the gap leaves work parked until it expires.

The **timeline index** is what makes peer dissemination incremental. Each peer is tracked by how far along the timeline it has been served, so a broadcast sends what that peer is missing rather than re-sending the pool. The timeline is bucketed rather than single-file, which keeps one heavy sender from monopolizing every broadcast slot.

## Dissemination and fairness

Nodes do not each learn about transactions independently. A node that accepts a transaction broadcasts it to peers, and peers are not treated identically — upstream peers are prioritized so a transaction moves toward the validators that can act on it rather than diffusing evenly across the network.

Fairness is tracked over recent history rather than enforced per message. The mempool keeps a rolling record of which senders and which kinds of traffic have recently consumed capacity, and uses it to shape what gets served next. This is the mechanism that keeps one account's order-and-cancel storm from crowding out the rest of the network, without needing a hard per-account rate limit that would penalize legitimate market making.

## Handoff to consensus

Consensus does not take transactions from the mempool one at a time. Transactions are gathered into **batches**, batches are disseminated to validators in the background, and each batch is acknowledged until its originator can prove that enough of the network holds it. Only then can a block proposal reference it.

The consequence is that a block proposal carries batch digests rather than transaction bodies, so consensus message size stays flat as throughput rises — and a committed block is always replayable, because the data behind it was proven available before it was referenced. See [IntentionBFT](/protocol/architecture/intention-bft) for how that proof is formed and used.

<Note>
  This is also why mempool admission is not the same as inclusion. A transaction that is accepted, stored, and broadcast has entered the queue; it has not been ordered. Nothing about a transaction's fate is settled until consensus commits the block that contains it.
</Note>

## What this means for a client

* **A rejection at submission is informative.** It happened before the transaction was stored, and the reason describes something the client can fix.
* **Silence is not rejection.** A transaction may be parked behind a gap of the client's own making. Track what has been submitted and what has committed rather than assuming a missing acknowledgement means a drop.
* **Order within an account matters; order across accounts does not.** Two transactions from one sender have a defined sequence. Two transactions from different senders are ordered by consensus, not by who submitted first.
* **Cancels are not privileged in the mempool.** Cancellation priority is a property of [kernel execution](/protocol/architecture/kernel), where cancels run before aggressive placements in the same block — not of queueing.
