What makes them interoperable at all
Four codebases in four languages route Lightning payments to each other every day, and the reason is narrow: the BOLT specifications define the bytes on the wire and say nothing about the program that emits them. BOLT 1 fixes the message framing, BOLT 2 the channel state machine, BOLT 3 the transaction and script formats, BOLT 4 the onion, BOLT 7 gossip, BOLT 8 the encrypted transport, BOLT 11 invoices. Everything above that line, the database, the interface, the way routes get chosen, is left open.
Each project says so in its own words. LND "fully conforms to the Lightning Network specification (BOLTs)". Core Lightning is "a specification compliant Lightning Network implementation in C". Eclair "follows the Lightning Network Specifications (BOLTs)". LDK "implements all of the BOLT specifications". The document itself is careful about its status: BOLT 0 opens by calling the set "version 0", still being drafted.
So interoperability is a property of the protocol, not a favour the projects do each other.
LND
Written in Go, and the licence carries the copyright of "Lightning Labs and The Lightning
Network Developers"; the official Docker images ship under lightninglabs/lnd. It is
described in its own README as "a complete implementation of a Lightning Network node", and
still labelled beta software.
It optimises for being built on. The README is explicit: "The daemon has been designed to
be as developer friendly as possible in order to facilitate application development on top
of lnd. Two primary RPC interfaces are exported: an HTTP REST API, and a gRPC service."
That choice shows up everywhere downstream, in the routing services, the exchange
integrations and the phone wallets that drive an LND node rather than implement Lightning
themselves. It also means LND's own behaviour is load-bearing for a lot of other software,
which is why a change to how it
bounds what one peer can make it buffer was worth
covering as news.
It also ships several pluggable chain backends rather than assuming one: bitcoind, the Go
full node btcd, and Neutrino, which its own
README still calls "a new experimental light client".
Core Lightning
Written in C, "developed and maintained by Blockstream", in production on mainnet since
early 2018 with the launch of the Blockstream Store. The daemon is lightningd, the client
lightning-cli, and the interface is "a JSON-RPC 2.0 interface over a Unix Domain socket".
It optimises for being extended, to the point where the daemon is a small core and much of
what you think of as the node is a plugin. Look in the repository's plugins directory and
you find not only conveniences but bcli, the Bitcoin backend itself, offers, keysend
and askrene, the route-finding oracle. The
plugin contract is deliberately
language-neutral: "A plugin may be written in any language, and communicates with
lightningd through the plugin's stdin and stdout. JSON-RPCv2 is used as protocol on
top of the two streams." Plugins register their own command line options and their own
JSON-RPC commands, subscribe to event streams, and use hooks to alter the daemon's
behaviour.
Eclair
Written in Scala, on the JVM, by ACINQ, and French for lightning. It targets Java 21, and requires a synchronised, segwit-ready, zeromq-enabled, wallet-enabled, non-pruning, transaction-indexing Bitcoin Core node. It has no on-chain wallet of its own: "channel opening transactions are funded by your Bitcoin Core node, and channel closing transactions return funds to your Bitcoin Core node."
It optimises for running a large routing node under load. The
architecture document
says the reason plainly: it leans on the actor model, so that almost every entity is a
separate sandboxed actor. Each peer connection is one, each channel is one, each payment
attempt is one, which is how the node isolates faults and scales across CPUs. It goes
further than the others in that direction with a
cluster mode that splits one
logical node across servers: stateless front servers absorb the gossip and sync traffic
(BOLT 1 and BOLT 7), while a single backend handles channel management (BOLT 2). The
interface is an HTTP JSON API, disabled by default and password-protected when enabled, and
plugins are JVM jars implementing a Plugin interface.
LDK, which is not a node
LDK is the exception, and the reason it belongs in this list is that a lot of software you have used is running it. It is a Rust library. Its README states the limit up front: "Note that LDK isn't, in itself, a node."
What that means practically is that LDK deliberately does not provide the things a daemon
would decide for you. On-disk storage, blockchain data, UTXO management, networking and
private keys are all left to the embedding application, each behind an interface. The core
lightning crate is runtime-agnostic and supports no_std. The project's own framing:
"if you want to integrate Lightning with custom features such as your own chain sync, key
management, data storage/backup logic, etc., LDK is likely your best option."
That is why LDK shows up inside wallets and payment platforms rather than as a process on a
server. Its site lists Lightspark, Alby Hub, Cash App and Lexe as projects built on it.
ACINQ does something similar with a separate codebase: Eclair is what it points routing node
operators at, while Phoenix, its phone wallet, is built
on lightning-kmp, a Kotlin implementation for mobile.
Where they legitimately differ
| LND | Core Lightning | Eclair | LDK | |
|---|---|---|---|---|
| Language | Go | C | Scala | Rust |
| Maintainer | Lightning Labs | Blockstream | ACINQ | LDK developers |
| Shape | daemon | daemon | daemon | library |
| Interface | gRPC and REST | JSON-RPC over a Unix socket | HTTP JSON API | Rust API, plus bindings |
| Extension | RPC subservers | plugins in any language | JVM plugins | your own code |
Database backends. LND stores state in an embedded bbolt database by default and can be
configured onto Postgres,
SQLite, or etcd, and
the etcd option exists to support
leader election
across a cluster where only one instance may write. Core Lightning takes a data source name,
sqlite3:// or postgres://. Eclair defaults to SQLite and supports PostgreSQL 10.6 and
above. LDK has no opinion, because persistence is the caller's job.
Watchtowers. LND ships one as a subsystem: a private altruist watchtower, plus a client
that backs up encrypted justice transactions to other towers, with the caveat in its own
docs that it currently covers the to_local and to_remote outputs of revoked commitments
and not HTLC outputs. Core Lightning does it through the plugin interface instead, exposing
a commitment_revocation hook that hands penalty transactions to
a watchtower service of your choosing.
Routing heuristics. This is where two nodes given the same graph disagree, because the
graph never says which side of a channel the money is on. LND keeps a subsystem called
mission control, described in its source as state that "acts as a shared memory during
routing attempts", tracking the time of the last failure per node and channel and turning
it into a success probability fed back into path finding. Its default penalty half-life is
one hour: a channel that failed is back to a 50% probability estimate after that. Core
Lightning's route finding lives in the askrene plugin, which combines what it knows into
"layers" you can ask questions with or without. The differences are visible as different
fees and different failure rates on the same payment.
What none of this means
It is not a security ranking. The BOLTs bind all four to the same commitment transactions and the same penalty mechanism, so the guarantee you are relying on is the protocol's, not the codebase's. Choose on operational fit, on the interface you have to program against, and on whose release notes you are willing to read.
None of them removes the requirement to be online. A node that is offline when a counterparty broadcasts a revoked state cannot respond within the window, which is why watchtowers exist at all. That is a property of the protocol, not of the implementation, and it is the sharpest difference between Lightning and running a base layer node, which can be offline for a month and catch up.
Implementation choice is not invisible, either. It decides your backup procedure and your migration path, and those are the parts that lose money. LND's static channel backup is an LND mechanism, not a network one, and its safety guide says restoring from one "is not a migration but an emergency procedure". A node's channels do not move house because you changed your mind about the software. Which one is under your wallet matters less than whether you have made a payment and a backup work.
Sources
- The BOLT specifications, Lightning Network in-progress specifications
- lnd, Lightning Labs and The Lightning Network Developers
- Core Lightning, Blockstream, and its plugin documentation
- Eclair, ACINQ, and its architecture and cluster documents
- rust-lightning and lightningdevkit.org
