Onion Messages: Lightning’s Private Messaging Layer
Written by Abdullahi Yunus
Most people know the Lightning Network as a fast way to send Bitcoin payments. It’s a network of computers (called nodes) connected by payment channels. When someone sends a payment, it travels through several nodes, and each step of the journey is protected using something called onion encryption.
But the technology that makes Lightning payments possible can do more than move money.
Think of Lightning like a network of roads connecting many cities. Right now, those roads are mainly used to deliver packages of money (bitcoin payments). But the roads could also carry letters, instructions, or other kinds of information.
Right now, Lightning nodes can only communicate directly with their immediate peers. If a node wants to communicate with another node it isn’t directly connected to, it usually has to use something outside the Lightning Network.
For example, fetching a payment invoice often requires making an HTTP request to a web server. That works, but it introduces several problems.
First, it can leak information. The server might learn your IP address, when you’re making the request, and that you’re about to make a payment.
Second, it introduces extra infrastructure outside Lightning. If the server goes down, the process breaks.
Third, it weakens Lightning’s privacy model, which was carefully designed around onion routing.
And that leads to the question, if Lightning already has a network that can privately route payments between nodes, why not use that same network to route messages too?
That’s exactly what onion messages are.
Onion messages are defined in the BOLT 4 specification. They allow nodes to send arbitrary data through the Lightning Network, using the same onion‑routing system used for payments, but without the extra payment machinery like channels, HTLCs, or liquidity locks.
In other words, onion messages turn Lightning from a payment-only network into a private communication layer.
This isn’t just a theoretical idea. Onion messages are already being used as a foundation for new Lightning features and protocols.
In this post, we’ll explore:
- How onion messages work
- How they differ from payment routing
- How they’re implemented in LND
How Onion Routing Works for Payments

Before we look at onion messages, it helps to understand how Lightning routes payments, since onion messages build on the same idea.
Imagine you want to send a package to someone across the country. You don’t deliver it directly yourself. Instead, it travels through several post offices, each forwarding it to the next one until it reaches the destination.
Lightning payments work in a similar way.
When a node wants to send a payment, it first finds a route through the network. That route is a sequence of nodes where each pair shares a payment channel.
Once the route is found, the sender creates something called a Sphinx packet, named after the cryptographic system it uses.
The important idea here is layered encryption.
Think of the packet like a package wrapped in multiple envelopes.
Each envelope contains instructions for one stop along the route. The first node opens the outer envelope. It reads instructions telling it where to send the package next. It forwards the remaining package. The next node does the same thing, removing the next layer and forwarding the packet again.
Eventually the packet reaches the final recipient, who opens the last layer and sees the payment details.
Another way to imagine this is like a relay race. Each runner only knows who handed them the baton and who they should pass it to next. No runner knows the entire route of the race.
This design provides strong privacy.
Each intermediate node only learns three things: who sent it the packet, where to forward it next and the forwarding instructions. It cannot see the full route, the sender, or the final destination.
Alongside this routing mechanism is something called an HTLC (Hash Time‑Locked Contract). A simple way to think about HTLCs is like a secure escrow lock. Funds are temporarily locked along the route, and they are only released when the recipient reveals a secret called the payment preimage.
When the recipient reveals this secret, it travels back along the same path and unlocks the payment at each step.
This ensures that the payment either succeeds everywhere or fails everywhere.
But there’s a downside. All of this machinery exists because we’re moving money. It requires payment channels, available liquidity, HTLC contracts and updates to channel balances. That’s a lot of work if all you want to do is send a message.
So developers asked a simple question. What if we kept the private routing, but removed everything related to payments?
That’s the idea behind onion messages.
Onion Messages: What They Are and How They Differ
Traditional Lightning routing is tightly connected to payments. Every hop in a payment route requires a channel with enough liquidity and an HTLC setup.
That’s like using a full armored money truck just to deliver a simple letter.
Onion messages strip all of that away.
They keep the encrypted routing, but remove the payment parts.
An onion message is defined in BOLT 4 as a standalone message type (msg type 513). It’s essentially a packet of encrypted data that can travel across the network using the same onion‑routing design.
But there are a few key differences:
No channel and HTLC required: A payment hop requires an active payment channel between nodes. An onion message only requires a network connection. For example, Alice can forward a message to Bob as long as they are connected peers, even if they don’t have a payment channel. This means the message network can be larger than the payment network, since any peer connection can act as a relay.
One-way by default: Payments involve a round trip because the recipient must reveal a secret to complete the transaction. Onion messages are much simpler. They are one‑way packets. The sender builds the packet and sends it into the network. After that, it simply travels hop by hop until it reaches its destination. You can think of this like dropping a letter into a mailbox. Once it’s sent, you don’t necessarily know the exact path it takes to reach the recipient.
Reply paths solve the response problem: If messages are one‑way, how can the recipient respond? The sender can include something called a ReplyPath. This is like including a self‑addressed return envelope inside the message. The recipient can place their reply inside this envelope and send it back through the network. The clever part is that the reply path is also hidden using route blinding, so the recipient doesn’t learn who the original sender is.
Blinded paths add recipient privacy: Normally, when a sender builds a route, they know who the final recipient is. But onion messages introduce blinded paths. With blinded paths, the final portion of the route is hidden from the sender. Imagine sending a letter to a reception desk in a large office building. The receptionist receives it and forwards it internally to the correct office. You never see the internal routing. That’s similar to how blinded paths work. The recipient creates a hidden route starting from an introduction node. The sender only knows how to reach that introduction point. From there, the message continues along the hidden path to the final destination. This provides powerful privacy guarantees. It allows situations where the sender doesn’t know the recipient’s node ID, intermediate nodes only know the next hop, and the recipient doesn’t know the sender.

This combination of reply paths and blinded paths is what gives onion messages their privacy properties. A full exchange can happen where neither side knows the other’s node identity, with each party hiding behind blinded routes.
The Denial-of-Service (DoS) question: One concern with onion messages is spam. Payment forwarding naturally limits traffic because it requires liquidity and HTLCs. But forwarding onion messages is basically free. That means someone could try to flood the network with messages. The current approach is rate limiting. Each node limits how many onion messages it will forward per peer per second. It’s a simple solution, but it helps prevent abuse while keeping the system lightweight.
Protocol Walkthrough: Inside LND
Let’s trace what happens when a node sends an onion message through the network in LND. The implementation is split across two main PRs: #9868 introduced the wire message and basic structures, with the forwarding logic following in #10089. The architecture that emerged reveals some interesting design choices.

The Wire Message
At the lowest level, an onion message on the wire is surprisingly simple. The OnionMessage type in the lnwire package (message type 513) is just two fields:
// lnwire/onion_message.go
type OnionMessage struct {
PathKey *btcec.PublicKey // route blinding ephemeral pubkey
OnionBlob []byte // Sphinx onion packet (BOLT 4), blinded by default
}The PathKey is used to derive the blinded node identity at each hop, while the OnionBlob carries the layered encrypted payloads, constructed the same way as payment, but using route blinding by default. Feature bits 38/39 (OnionMessagesRequired/OnionMessagesOptional) signal support during the init handshake.
Per-peer Actors
Rather than processing onion messages inline in the peer’s read loop, LND uses an actor-based architecture. During peer connection, after the init handshake, the LND node checks whether the remote side peer advertises feature bit 38/39 and, if so, spawns a dedicated OnionPeerActor:
// peer/brontide.go — Start()
if p.remoteFeatures.HasFeature(lnwire.OnionMessagesOptional) {
// Start an actor primitive specifically for handling onion messages
// for this peer.
ref, spawnErr := p.cfg.SpawnOnionActor(p.cfg.ActorSystem, ...)
// ...
}When a type 513 message arrives, the read handler for the local node dispatches it directly to the actor with a fire-and-forget Tell:
// peer/brontide.go - readHandler
case *lnwire.OnionMessage:
p.onionActorRef.WhenSome(func(ref onionmessage.OnionPeerActorRef) {
ref.Tell(ctx, onionmessage.NewRequest(*msg))
})Decoding and Routing
The actor delegates the heavy lifting to processOnionMessage in hop.go. Onion messages use a separate Sphinx router initialized without replay protection since no funds are at stake:
// server.go - the onion message router uses a no-op replay log
sphinxOnionMsg := sphinx.NewRouter(nodeKeyECDH, sphinx.NewNoOpReplayLog())
The snippet below shows how LND determines action to take after it decodes the Sphinx packet and decrypts the blinded hop data using the path key. LND uses a sum type pattern to represent the result, either a forwardAction or a deliverAction, depending on whether we’re a relay or the final destination:
// onionmessage/hop.go - the routing decision
if isForwarding(packet) {
// For forwarding action, resolve nextNodeId either directly
// or using a short channel Id (SCID)
if routeData.NextNodeID.IsSome() {
nextNodeID = routeData.NextNodeID.UnwrapOrErr(…)
} else {
nextNodeID = resolver.RemotePubFromSCID(ctx, routeData.ShortChannelID…)
}
return fn.NewLeft(forwardAction {…})
}
return fn.NewRight(deliverAction{payload: payload})For forwards, a new OnionMessage with the updated path key and remaining onion blob is sent to the next peer via the PeerMessageSender interface. You can think of this like a postal sorting center. Each center checks the address and decides whether to forward the letter or deliver it. For deliveries, we’re the final destination, and the payload (including any ReplyPath and other TLV records) is handled.
The Opt-out Flag
LND also gives node operators the choice to opt out. It supports a `— protocol.no-onion-messages` flag. When set, the node doesn’t advertise feature bits 38/39, the actor factory is never created, and no per-peer actors are spawned; incoming onion messages are simply ignored. This lets node operators control their participation in message routing.
What Onion Messages Unlock
Onion messages, on their own, are a low-level building block, a way to get encrypted data from one node to another over the network. Their value becomes clear when you look at what can be built on top of them.
The most significant protocol development based on onion messages is BOLT 12, which introduces a native way for nodes to request and receive invoices directly over the Lightning Network, replacing the out-of-band invoice fetching we discussed earlier.
Today, if you want to pay a merchant, you usually have to fetch an invoice from a web server. That means leaving the Lightning Network and making a request over the internet. With BOLT 12, things work differently. A merchant can publish a small piece of information called an offer, which acts like a permanent payment endpoint. When a customer wants to pay, their node sends an onion message requesting an invoice. The merchant replies with the invoice using a reply path.
You can imagine this like ordering food at a restaurant using a private internal messaging system instead of calling an external phone line.
Everything happens inside the Lightning Network, improving privacy and reliability. Blinded paths and reply paths make this exchange possible while preserving privacy on both sides.
BOLT 12 is already supported in other implementations like CLN and Eclair, and its arrival in LND will be a meaningful step toward cross-implementation interoperability.
And offers are just the beginning. Onion messages provide a general-purpose transport layer that any application-level protocol can use. Node-to-node communication, custom application data, coordinated channel management, anything that currently relies on external infrastructure could potentially move onto the network itself, inheriting its privacy properties in the process.
What's most exciting about contributing to this in LND is how foundational the work is. Onion routing isn’t a feature end users interact with directly; it’s plumbing. But it’s the kind of plumbing that removes constraints. Today, building anything on Lightning that goes beyond a simple payment means reaching outside the network. Onion messages close that gap. The protocol surface area they open up is large, and we’re still early in exploring what’s possible.
Conclusion
Onion routing has always been a core part of Lightning’s privacy. Originally, it was designed specifically for payments. But onion messages extend the same idea to general communication.
By removing the payment‑specific requirements while keeping the privacy guarantees, onion messages allow nodes to exchange encrypted information across the network.
You can think of this as adding a private messaging system to Lightning’s infrastructure. Most users will never interact with it directly. But it quietly expands what the network can do.
And as developers continue experimenting with this new capability, we’re likely to see many new protocols built on top of it. In other words, Lightning may turn out to be not just a payment network, but also a private communication layer for the internet.
If you’re interested in following the progress in LND or contributing yourself, check the LND repo. The specification itself lives in BOLT 4. And if this post piqued your curiosity about how the pieces fit together, the best way to learn is to read the code.