Introduction to Corda flows

September 02, 2021

What is Flow?

Flow is a place where you put your business logic. You can think of it as the main function in C++ or Java, but you start it via RPC (hence you have @StartableByRPC annotation for your flow).

Why we need Flows?

Since we are on the network, you can communicate or transact with other parties only via flows, so if you want to come to a consensus about a particular fact with another node on the network. You can propose it, sign it and send it to another node for approval in a flow. It will run a contract and sign it and send it back — all done in its flow. Only after you receive all signatures can you notarize it (to prevent double-spends in case of digital assets being modified), and this fact will be successfully stored in our and our counterparty vault.

To initiate a flow, you need to annotate your flow with @InitiatingFlow and for the responder flow.

How does the counterparty flow know who to respond to? the counterparty flow has @InitiatedBy annotation.

How to start/stop a Flow?

You can call flows via node shell 🐚 , use start FlowName [par1, …] where par1,… is a list of constructor parameters. Let’s look at the example of ping-pong corDapp, which spins out two nodes (PartyA and PartyB) and sends a message “Ping” from one node to another. Then another node replies with “Pong” back. You can start flow bypassing the name of the flow:

>>> start PingFlow

but if your flow constructor requires parameters to start the flow. and you didn’t pass all of them — you will get an error message with a hint on how to call your flow:

No matching constructor found:

– [recipient: Party]: missing parameter recipient

because PingFlow constructor needs one parameter

public PingFlow(Party recipient){

   this.recipient = recipient;


let’s call PingFlow again with the recipient attribute:

>>> start PingFlow recipient: PartyA

in the shell, you can also get the info about the flows running the node.

You can see all flows available in the node by running the flow list. You can watch flows that are running in your node by typing flow watch. If your counterparty node is down, then your initiating flow will wait indefinitely on the response. You can kill a flow by pressing Ctrl+C (in case it doesn’t respond). In production, you can use a flow hospital.

Flow hospital

Flow hospital is a built-in service that oversees erroring flows. Flow hospital diagnoses, record, track, retry and recover flows. It determines the path for a flow, whether to propagate flow’s error or a flow should be retried from the last checkpoint. There are two reasons for a flow to be hospitalized: first, if the counterparty flow is not installed on its node, which triggers ClassNotFoundException inside an initiating flow. The second case is when a runtime error occurs. Then the initiation session stays in the hospital for error handling and observation. The errors that the hospital handles are deadlock, database constraint violation, database connection errors or other SQLException. Also exceptions during ReceiveFinalityFlow handling, FlowTimeoutException threw by Notary, HospitalizeFlowException with aim to retry from last flow checkpoint, and lastly, any internal Corda exceptions from Corda State machine are handled by the hospital.

Ledger query from flows

Through Vault query API, a developer can query via static (current result) or dynamic (current result with future updates) functionality to obtain data. The QueryCriteria interface, which is enriched with binary, comparison, equality, and other operators, can specify filter criteria. There are four filterable QueryCriteria types:

  1. VaultQueryCriteria is a way to filter on attributes within the VAULT_STATES table.
  2. VaultCustomQueryCriteria is a criterion over arbitrary expressions and attributes defined by a custom contract state that implements its own schema.
  3. FungibleAssetQueryCriteria is a criterion on an attribute from FungibleAsset contract state interface.
  4. LinearStateQueryCriteria is a set of filterable criteria on attributes DealState contract state interfaces.

As you can see, it’s vital to understand what flow functionality is available during your CorDapp development. Also, Corda treats errors thrown inside the flows by having Flow Hospital in the node.