What is an app ledger?
An app ledger is an application-specific, replicated ledger that a group of organizations runs together. Each organization runs a member node. Members agree on the order of application messages, apply them with the same deterministic state machine, and each derives the same authenticated state root on its own. Records in that state can be proved against the root, and the root can optionally be anchored on Cardano.
The shortest description:
A programmable, multi-party application ledger with deterministic state, threshold finality, proofs, Cardano anchoring, and controlled external actions.
Yano’s command line, configuration, and APIs call an app ledger an app chain.
You will see ./yano.sh appchain commands, yano.app-chain.* settings, and
/api/v1/app-chain/ URLs. They refer to the same thing.
The problem it solves
Section titled “The problem it solves”Many business processes span several organizations and systems, and today they usually look like this:
- each participant keeps its own database;
- one operator controls the shared API or message broker;
- audits reconstruct history after the fact;
- external actions are hard to tie back to an agreed business decision; and
- putting every application event directly on a public blockchain is too slow, too costly, too public, or too inflexible.
An app ledger gives the participants a shared application layer without turning every business operation into a Cardano transaction.
- App ledger · the same rules on every member: Ordered messages, State machine, Final block, State root.
- External systems: Kafka, IPFS, Object storage, ERP or webhook.
- Organization A → App ledger · the same rules on every member.
- Organization B → App ledger · the same rules on every member (messages).
- Organization C → App ledger · the same rules on every member.
- Ordered messages → State machine.
- State machine → Final block.
- Final block → State root.
- State root → Cardano (anchor).
- Final block → Effect runtime (effects).
- Effect runtime → External systems.
Select any block to see what it does.
- Organization A
- Each organization runs a member node, identified by an Ed25519 key. Its applications submit messages through that member, and the member votes on every block.
- Organization B
- Each organization runs a member node, identified by an Ed25519 key. Its applications submit messages through that member, and the member votes on every block.
- Organization C
- Each organization runs a member node, identified by an Ed25519 key. Its applications submit messages through that member, and the member votes on every block.
- Ordered messages
- An application submits a topic and a body to a member, which signs the envelope with its member key. Members gossip pending messages, and the leader for each height orders them into a block. Life of a message →
- State machine
- The only component that reads message bodies. Every member applies the same messages with the same deterministic code, so honest members reach the same state. State machines →
- Final block
- A block is final once a threshold of members has signed PREPARE and then COMMIT for it, each after re-executing it. There is no rollback below finality. Consensus and finality →
- State root
- The root of the authenticated state after a block, identical on every member. A proof shows that a record is, or is not, present under this root. State and proofs →
- Cardano
- An anchor publishes a certified state root to Cardano, in transaction metadata or a script-controlled anchor. It is optional, and finality never waits for it. Cardano anchoring →
- Effect runtime
- A transition can emit an effect record. After finality, an executor outside consensus performs the external action, and a tracked result returns to the ledger as a new message. Effects →
- Kafka
- Effects reach systems like these. Yano X ships optional connectors for Kafka, S3-compatible object storage, IPFS/Kubo, and Cardano payments; the Yano host provides HTTP webhooks.
- IPFS
- Effects reach systems like these. Yano X ships optional connectors for Kafka, S3-compatible object storage, IPFS/Kubo, and Cardano payments; the Yano host provides HTTP webhooks.
- Object storage
- Effects reach systems like these. Yano X ships optional connectors for Kafka, S3-compatible object storage, IPFS/Kubo, and Cardano payments; the Yano host provides HTTP webhooks.
- ERP or webhook
- Effects reach systems like these. Yano X ships optional connectors for Kafka, S3-compatible object storage, IPFS/Kubo, and Cardano payments; the Yano host provides HTTP webhooks.
The app ledger does not replace Cardano. It supplies application-specific execution and coordination; Cardano supplies an independently observable record of the state roots the ledger commits to.
What makes it a ledger rather than a shared database
Section titled “What makes it a ledger rather than a shared database”| Characteristic | What it means | Why it matters |
|---|---|---|
| Signed participation | Every message travels in an envelope signed by the member that accepted it. People and organizations who approve a business decision sign that decision themselves, inside the message. | The ledger knows which member submitted a message and who approved an action. |
| Deterministic execution | Every member applies the same messages, in the same order, with the same state machine. | Honest members derive the same state root, byte for byte. |
| Threshold finality | A block is final once the configured number of members has signed it in two rounds of votes, PREPARE and COMMIT. | No single database or broker operator decides history. |
| Hash-linked blocks | Each block commits to the block before it. | Reordering or rewriting history is detectable. |
| Provable state | State is held in an authenticated tree that supports inclusion and exclusion proofs. Its type, MPF or JMT, is fixed when the ledger is created. | A client checks a record against a root without trusting one node. |
| Cardano anchoring | A certified state root can be published in Cardano transaction metadata or in a script-controlled anchor. | Auditors can tie the ledger’s evidence to public Cardano history. |
| Deterministic effects | External work is authorized by an immutable effect record that the state machine emits. | Network calls never run inside consensus execution. |
| Catch-up and recovery | Restarted or new members fetch history and verify every block and certificate themselves. | Recovery does not require trusting a database copy. |
| Plugins | State machines, executors, sinks, APIs, and queries are extensible. | A domain can evolve without forking the consensus framework. |
Life of a message
Section titled “Life of a message”Follow one message from an HTTP call to a final, provable result. The “What if” scenarios show what happens when a business rule fails, when the leader is offline, and when one member computes a different result.
What you're seeing: three members, any 2 of which make a block final. Pick a step, press Play, or try a “What if”. Switch to your application’s view to see only what an HTTP caller sees.
- Submit Your application sends a topic and a body to Member A, over REST or the Java client. It signs nothing: Member A wraps the body in an envelope signed with its own member key. When a decision needs a person or organization to approve it, their signatures travel inside the body.You send a topic and a body to one member. You do not sign the envelope.
- Admit Member A asks the state machine whether the command is acceptable at the next height. If it is, A keeps the message in its pending pool and answers 202 with a message id. A 400 means the application refused it; 429 means the pool is full. 202 only means "queued on Member A".You receive 202 and a message id. Nothing is final yet, and nothing has succeeded yet.
- Gossip Member A gossips the envelope to the other members. Each checks the signature and that A is a member, drops duplicates by message id, and holds the message in memory. Pending pools are not saved: a message no other member has received is lost if A restarts. An envelope expires after 10 minutes by default.Still pending. The message is waiting in the members’ pools.
- Propose Member B leads this height. On its next tick (every 2 seconds by default) it selects pending messages, checks them again against the current state, applies the block itself to compute the new state root, records a prepare lock, and sends the block with its PREPARE vote. No pending messages, no block.Still pending. A block containing your message is being proposed.
- Re-execute Members A and C do not trust the root Member B sent. Each checks the leader, the link to the previous block, every message signature, and the block size, then applies the block itself and compares the state root byte for byte. A member votes PREPARE only for a root it computed itself.Still pending. Every member is re-running the block.
- passes: Height is exactly one above the local tip
- passes: The sender is the leader for this height and view
- passes: The block links to the local tip hash
- passes: The messages root recomputes from the messages
- passes: Every message is signed by a member at this height and has not expired
- passes: No conflicting prepare lock in this view
- passes: Re-executing the block gives a byte-identical state root
- Prepare PREPARE votes reach the threshold, 2 of 3 here. A member holding them forms a PreparedQC: signed evidence that a quorum accepted this exact block. Members then sign COMMIT.Still pending.
- Commit When COMMIT votes reach the threshold, a member assembles the finality certificate and shares it. Every member writes block h and its new state in one atomic batch. The block is final, and there is no rollback below finality.Your message is final at height h.
- Read and prove Your application finds the message at its height and index, reads the application’s result, and can request a proof that a record is, or is not, in the state under the certified root. Always check the result: a final command that breaks a business rule is recorded as a no-op.Read the result and fetch a proof. Do not treat 202 as success.
- Anchor Optionally, an anchor later publishes a certified state root to Cardano, giving auditors a public reference that does not depend on any member. Finality never waits for Cardano.Optional: a later anchor covers your message on Cardano.
What if: A rule fails after 202
Admission said yes, but by the time the block ran, the state had changed.
- Submit Your application sends a topic and a body to Member A, over REST or the Java client. It signs nothing: Member A wraps the body in an envelope signed with its own member key. When a decision needs a person or organization to approve it, their signatures travel inside the body.You send a topic and a body to one member. You do not sign the envelope.
- Admit Member A asks the state machine whether the command is acceptable at the next height. If it is, A keeps the message in its pending pool and answers 202 with a message id. A 400 means the application refused it; 429 means the pool is full. 202 only means "queued on Member A".You receive 202 and a message id. Nothing is final yet, and nothing has succeeded yet.
- Gossip Member A gossips the envelope to the other members. Each checks the signature and that A is a member, drops duplicates by message id, and holds the message in memory. Pending pools are not saved: a message no other member has received is lost if A restarts. An envelope expires after 10 minutes by default.Still pending. The message is waiting in the members’ pools.
- Propose Member B leads this height. On its next tick (every 2 seconds by default) it selects pending messages, checks them again against the current state, applies the block itself to compute the new state root, records a prepare lock, and sends the block with its PREPARE vote. No pending messages, no block.Still pending. A block containing your message is being proposed.
- Re-execute Members A and C do not trust the root Member B sent. Each checks the leader, the link to the previous block, every message signature, and the block size, then applies the block itself and compares the state root byte for byte. A member votes PREPARE only for a root it computed itself.Still pending. Every member is re-running the block.
- passes: Height is exactly one above the local tip
- passes: The sender is the leader for this height and view
- passes: The block links to the local tip hash
- passes: The messages root recomputes from the messages
- passes: Every message is signed by a member at this height and has not expired
- passes: No conflicting prepare lock in this view
- passes: Re-executing the block gives a byte-identical state root
- Prepare PREPARE votes reach the threshold, 2 of 3 here. A member holding them forms a PreparedQC: signed evidence that a quorum accepted this exact block. Members then sign COMMIT.Still pending.
- Commit When COMMIT votes reach the threshold, a member assembles the finality certificate and shares it. Every member writes block h and its new state in one atomic batch. The block is final, and there is no rollback below finality.Your message is final at height h.
- Final, as a no-op The block is final, but the command broke a business rule against the state it actually ran on: another message changed that state first. Every member records the same no-op. The message id is now used: correct the cause and submit a new message to retry.The message is final, but your command had no effect. Submit a new message to retry.
What if: The leader is offline
A quorum moves the round to the next member. No configuration change is needed.
- Submit Your application sends a topic and a body to Member A, over REST or the Java client. It signs nothing: Member A wraps the body in an envelope signed with its own member key. When a decision needs a person or organization to approve it, their signatures travel inside the body.You send a topic and a body to one member. You do not sign the envelope.
- Admit Member A asks the state machine whether the command is acceptable at the next height. If it is, A keeps the message in its pending pool and answers 202 with a message id. A 400 means the application refused it; 429 means the pool is full. 202 only means "queued on Member A".You receive 202 and a message id. Nothing is final yet, and nothing has succeeded yet.
- Gossip Member A gossips the envelope to the other members. Each checks the signature and that A is a member, drops duplicates by message id, and holds the message in memory. Pending pools are not saved: a message no other member has received is lost if A restarts. An envelope expires after 10 minutes by default.Still pending. The message is waiting in the members’ pools.
- No proposal Member B, the leader for view 0, is down. No block arrives, and A and C keep the message in their pools.Still pending.
- Time out The round times out, after 10 seconds by default. A and C each sign a TIMEOUT for view 1. Two of three is the threshold, so together they form a new-view certificate.Still pending; the round is being retried.
- Next leader The next member in the fixed member order, here Member C, leads view 1. It must re-propose any block that already has a PreparedQC; otherwise it builds a new block from its pool and sends its PREPARE.Still pending.
- Final without B Member A re-executes the block and votes. Two PREPAREs and two COMMITs make block h final. When B returns, it catches up by verifying each block and its certificate before applying it.Your message is final at height h.
What if: One member disagrees
A member that computes a different root refuses to vote.
- Submit Your application sends a topic and a body to Member A, over REST or the Java client. It signs nothing: Member A wraps the body in an envelope signed with its own member key. When a decision needs a person or organization to approve it, their signatures travel inside the body.You send a topic and a body to one member. You do not sign the envelope.
- Admit Member A asks the state machine whether the command is acceptable at the next height. If it is, A keeps the message in its pending pool and answers 202 with a message id. A 400 means the application refused it; 429 means the pool is full. 202 only means "queued on Member A".You receive 202 and a message id. Nothing is final yet, and nothing has succeeded yet.
- Gossip Member A gossips the envelope to the other members. Each checks the signature and that A is a member, drops duplicates by message id, and holds the message in memory. Pending pools are not saved: a message no other member has received is lost if A restarts. An envelope expires after 10 minutes by default.Still pending. The message is waiting in the members’ pools.
- Propose Member B leads this height. On its next tick (every 2 seconds by default) it selects pending messages, checks them again against the current state, applies the block itself to compute the new state root, records a prepare lock, and sends the block with its PREPARE vote. No pending messages, no block.Still pending. A block containing your message is being proposed.
- A different root Suppose Member C runs a different build of the state machine plugin than A and B, so the same messages give it a different state root. C does not vote: a member never accepts a root it did not compute itself.Still pending.
- passes: Height is exactly one above the local tip
- passes: The sender is the leader for this height and view
- passes: The block links to the local tip hash
- passes: The messages root recomputes from the messages
- passes: Every message is signed by a member at this height and has not expired
- passes: No conflicting prepare lock in this view
- fails: Re-executing the block gives a byte-identical state root
- The quorum finalizes Members A and B are two of three, so block h is still final. Member C cannot apply the certified block, because its result differs, so C stalls until its operator fixes the cause. If a quorum disagreed, no block would become final: the ledger stops rather than accept a disputed state.Your message is final at height h.
- your application
- member node
- leader for the round
- final
- refused or stalled
Three things follow from this flow:
- 202 is not success. It means one member queued the message. Wait for the block, then read the application’s result. A final command that breaks a business rule is recorded as a no-op on every member.
- No member is trusted with the result. Every member re-executes every block, and the finality certificate shows that a threshold of them computed the same root.
- The ledger fails closed. Envelope signatures, membership at each height, the leader for each round, hash links, and the re-executed state root are checked on every member, always. A member that computes a different root does not vote, and if too few members agree, no block becomes final.
Consensus and finality describes the round in more detail.
Vocabulary
Section titled “Vocabulary”| Term | Meaning |
|---|---|
| App ledger | A replicated application ledger run by a group of members. Yano’s tooling calls it an app chain. |
| Chain id | The identifier of one app ledger (chain-id in configuration). The same members may run several independent ledgers, and one node can host several. |
| Member | A node that takes part in a ledger, identified by an Ed25519 public key. Members sign the envelopes of messages they accept, check and vote on blocks, and each hold the full state. A ledger has at most 32 members. |
| Actor | A person or organization that signs a business decision, such as an approval, inside a message. Actors are separate from members. |
| Leader | The member that proposes the block for a height and view. With a fixed sequencer, a configured member leads view 0; with a rotating sequencer, the view-0 leader is derived from the previous block. If a round times out, a threshold of members moves to the next view, and the next member in order leads. |
| Threshold | How many members must vote for a block before it is final. |
| Finality certificate | The threshold of COMMIT signatures that makes a block final. |
| App message | An envelope with a topic and an opaque body, signed by the member that accepted it. Only the state machine interprets the body. |
| Topic | A label inside a ledger, for routing and filtering messages. |
| App block | An ordered batch of messages, the state root after applying them, a hash link to the previous block, and the block’s finality certificate. |
| State root | The root of the authenticated state after a block. Identical on every member, provable, and anchorable on Cardano. |
| State machine | The only component that interprets message bodies. |
| Effect | An immutable record emitted by a transition, authorizing external work that an executor performs after finality. |
| Anchor leader | The single node that builds, pays for, and submits anchor transactions. Its powers depend on the anchor mode; script anchors also require member signatures. |
When an app ledger is the right answer
Section titled “When an app ledger is the right answer”An app ledger is useful when several of these needs apply:
- several organizations must agree on the same sequence of application records;
- no single participant should own the authoritative database;
- someone will later need to prove a specific record, not merely be told about it;
- the volume, privacy, or cost profile makes putting each event directly on a public chain impractical; and
- some external systems must act on decisions, but only after those decisions are final.
It is not the right answer for a single-organization application with no external verifier, for high-frequency data with no dispute surface, or for anything that genuinely needs permissionless participation.
What you're seeing: four questions drawn from the criteria on this page. Answer them for your use case.
Who needs to agree on the records?
- One organization, and nobody outside it checks themA conventional database is simpler
With one organization and no outside verifier, replicated agreement adds cost without adding trust.
- Several organizations
Who may take part?
- Anyone, without permissionUse a public blockchain
An app ledger has a known set of members. Permissionless participation needs a public chain such as Cardano itself.
- Known organizations that run members
Will someone later need to prove a specific record, rather than be told about it?
- Yes, records can be disputed or audited
Could every event go directly onto a public chain?
Think about event volume, privacy, cost, and how custom the rules are.
- Yes: few events, public data, simple rulesConsider Cardano directly
When events are few, public, and simple, writing them to Cardano gives independent verification without running members.
- No: too many events, private data, or custom rulesAn app ledger fits
Several known organizations need the same ordered records, verifiable proofs, and rules of their own, at a volume or privacy level a public chain cannot carry. Anchor to Cardano when outsiders need a public reference.
- Try it
- a three-member ledger on your laptop
- Then
- pick a recipe for your rules
- Yes: few events, public data, simple rules
- No, it is high-frequency data with nothing to disputeA shared service is probably enough
If nobody will dispute the data, a shared database or message broker run by one party is simpler. Revisit this if records start to matter in audits or disputes.
- Yes, records can be disputed or audited
- Anyone, without permission
Who needs to agree on the records?
Who may take part?
Will someone later need to prove a specific record, rather than be told about it?
Could every event go directly onto a public chain?
Think about event volume, privacy, cost, and how custom the rules are.
With one organization and no outside verifier, replicated agreement adds cost without adding trust.
An app ledger has a known set of members. Permissionless participation needs a public chain such as Cardano itself.
If nobody will dispute the data, a shared database or message broker run by one party is simpler. Revisit this if records start to matter in audits or disputes.
When events are few, public, and simple, writing them to Cardano gives independent verification without running members.
Several known organizations need the same ordered records, verifiable proofs, and rules of their own, at a volume or privacy level a public chain cannot carry. Anchor to Cardano when outsiders need a public reference.
- Try it
- a three-member ledger on your laptop
- Then
- pick a recipe for your rules
Where Yano and Yano X fit
Section titled “Where Yano and Yano X fit”Yano is the host: a Cardano data node with a minimal app ledger runtime,
consensus, proofs, anchoring, the effect system, the plugin SPI, and
ordered-log as its only built-in state machine.
Yano X is the extension ecosystem on top: the stock state machines, the composition framework, connectors, products, SDKs, tooling, and the batteries-included JVM distribution.
Next: Why Yano X.