Parallel nodes: fan-out with edges
Two edges out of one node run both next nodes in the same step. That is fan-out: fixed parallel work, wired at build time.
Last updated: 27 Sep, 2026 · LangGraph 1.2
Some checks do not depend on each other, so running them one after another wastes time. Give a node two outgoing edges and both next nodes run together.
The fan-out edges
builder.add_edge(START, "check_a") # both run
builder.add_edge(START, "check_b") # in the same step
builder.add_edge("check_a", "join") # both feed the next node
builder.add_edge("check_b", "join") # which runs once, after bothThe imports
Start with the imports. add is the reducer that will join the two parallel writes.
from operator import add
from typing_extensions import TypedDict, Annotated
from langgraph.graph import StateGraph, START, ENDThe state
Define the state. The notes key uses the add reducer, so when two nodes write it in the same step their lists are joined instead of one overwriting the other.
class State(TypedDict):
notes: Annotated[list[str], add] # add joins the two parallel writes into one listThe three nodes
Write three node functions. The two checks do not read each other's output, so they can run side by side. summarise runs after both.
def check_account(s): return {"notes": ["account ok"]} # one independent check
def check_payment(s): return {"notes": ["payment ok"]} # the other, no shared data
def summarise(s): return {"notes": ["done"]} # runs after both checksWiring the fan-out
Wire the graph. Two edges leave START, and each check has an edge into summarise.
b = StateGraph(State)
b.add_node("check_account", check_account)
b.add_node("check_payment", check_payment)
b.add_node("summarise", summarise)
b.add_edge(START, "check_account") # both edges out of START
b.add_edge(START, "check_payment") # fire in the same step
b.add_edge("check_account", "summarise") # each check feeds summarise
b.add_edge("check_payment", "summarise") # which waits for both
b.add_edge("summarise", END)- Both edges out of
STARTfire, socheck_accountandcheck_paymentrun in the same step. summarisehas an edge from each check, so it waits for both and runs once, not twice.
Running the graph
Compile the graph and run it with an empty notes list, then print the result.
print(b.compile().invoke({"notes": []})["notes"]) # both checks, then the summaryTwo checks in one step
The same pieces in one file, ready to run.
from operator import add
from typing_extensions import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
notes: Annotated[list[str], add]
def check_account(s): return {"notes": ["account ok"]}
def check_payment(s): return {"notes": ["payment ok"]}
def summarise(s): return {"notes": ["done"]}
b = StateGraph(State)
b.add_node("check_account", check_account)
b.add_node("check_payment", check_payment)
b.add_node("summarise", summarise)
b.add_edge(START, "check_account")
b.add_edge(START, "check_payment")
b.add_edge("check_account", "summarise")
b.add_edge("check_payment", "summarise")
b.add_edge("summarise", END)
print(b.compile().invoke({"notes": []})["notes"])How the parallel writes joined
- Both edges out of
STARTfire, socheck_accountandcheck_paymentrun in the same step. summarisehas an edge from each check, so it waits for both and runs once, not twice.- The two parallel writes need the
addreducer onnotes; without it both nodes try to setnotesin the same step and collide.
Parallel edges vs Send
| Parallel edges | Send | |
|---|---|---|
| Runs | A fixed set of different nodes | The same node, once per item |
| Count known | At build time | Only at run time |
| Use for | Do A and B side by side | Map over a list |
When to run steps side by side
- Running independent checks or lookups at once, then combining them.
- Fetching from two sources in parallel before an answer.
Related
- Previous: Reducers: combining values in the state
- Next: Command: update and route in one step
- See also: Send: run one node per item
- Add a third parallel check and confirm all three notes appear.
- Remove the reducer on
notesand read the error.
This is what real progress feels like.