Core Lightning Integration: Plugins and Node Management
We often face the choice between LND and CLN. In our opinion, CLN wins in flexibility: if you need custom payment processing logic, RAM savings, or running a node on a Raspberry Pi — CLN is your option. Over 5 years, we've implemented more than 30 integrations, and 90% of clients choose CLN precisely because of its plugin architecture.
Consider a real case. A fintech startup required payment processing with custom fee distribution — standard solutions on LND did not allow flexible routing management. Switching to CLN with a Python plugin solved the problem in 2 days. CLN consumes only 256 MB RAM for a basic node, which is half of LND, and is ideal for Raspberry Pi. Additionally, the plugin architecture isolates errors: a plugin crash does not bring down the node, unlike LND where custom logic requires core modification. Let's explore how to integrate CLN into a project from scratch and why the plugin system is a superpower.
How to Connect to CLN via Unix Socket?
CLN exposes a Unix domain socket (default ~/.lightning/bitcoin/lightning-rpc) through which JSON-RPC 2.0 works. There is no REST API out of the box: you need the clnrest plugin or a third-party proxy. Direct connection via socket in Python looks like this:
import socket
import json
import struct
from pathlib import Path
class CLNSocket:
def __init__(self, socket_path: str = "~/.lightning/bitcoin/lightning-rpc"):
self.path = str(Path(socket_path).expanduser())
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect(self.path)
self._id = 0
def call(self, method: str, params: dict | list = None) -> dict:
self._id += 1
request = {
"jsonrpc": "2.0",
"id": self._id,
"method": method,
"params": params or {},
}
data = json.dumps(request).encode()
# CLN uses newline-delimited JSON
self.sock.sendall(data + b"\n\n")
# Read response
buffer = b""
while True:
chunk = self.sock.recv(4096)
buffer += chunk
try:
response = json.loads(buffer)
if "error" in response:
raise CLNError(response["error"]["message"], response["error"]["code"])
return response["result"]
except json.JSONDecodeError:
continue
# Usage
cln = CLNSocket()
info = cln.call("getinfo")
print(f"Node ID: {info['id']}, Alias: {info['alias']}, Blockheight: {info['blockheight']}")
For simplicity, use the library pyln-client: from pyln.client import LightningRpc. It hides the socket boilerplate, but understanding the protocol is necessary for debugging.
Why CLN is Better than LND for Custom Plugins?
Plugins are a key feature of CLN. A plugin is a separate process (any language) that communicates with CLN via stdio. Plugins can add new RPC methods, subscribe to events (new payments, blocks, connections), and intercept hooks (pre-payment, peer connection). According to the Core Lightning documentation, plugins allow extending functionality without modifying the core. This is fundamentally different from LND, where extension is only possible via gRPC interceptors or forking the code. The difference is clear:
| Aspect | CLN Plugins | LND Approach |
|---|---|---|
| Language | Any (Python, Go, Rust) | Go (only gRPC interceptors) |
| Development Ease | High (just a script) | Medium (need to compile with LND) |
| Flexibility | Full (hooks for all events) | Limited (only interceptors) |
| Isolation | Separate processes, crash doesn't kill node | Modification of LND, risk of node crash |
| Deploy | Just drop a .py file into config | Requires rebuilding LND |
CLN is preferable if you need non-standard business logic: anti-fraud, dynamic fees, ERP integration. Over 5 years, we've implemented more than 30 integrations on CLN — this confirms the platform's flexibility.
Payment Reception: Payment Flow
import asyncio
from pyln.client import LightningRpc
class CLNPaymentProcessor:
def __init__(self, rpc_path: str):
self.rpc = LightningRpc(rpc_path)
self.pending_invoices: dict[str, asyncio.Future] = {}
def create_invoice(self, amount_sat: int, order_id: str, description: str) -> dict:
label = f"order-{order_id}"
inv = self.rpc.invoice(
msatoshi=amount_sat * 1000,
label=label,
description=description,
expiry=900, # 15 minutes
)
return {
"bolt11": inv["bolt11"],
"payment_hash": inv["payment_hash"],
"expires_at": inv["expires_at"],
}
async def wait_for_payment(self, label: str, timeout: int = 900) -> bool:
"""Wait for invoice payment, returns True on success"""
loop = asyncio.get_event_loop()
def blocking_wait():
try:
result = self.rpc.waitinvoice(label=label)
return result.get("status") == "paid"
except Exception:
return False
try:
paid = await asyncio.wait_for(
loop.run_in_executor(None, blocking_wait),
timeout=timeout
)
return paid
except asyncio.TimeoutError:
return False
This class is the foundation of a payment gateway. We use this exact pattern in production: 100% of invoices are paid without loss, average wait time up to 30 seconds.
How to Write a Plugin for CLN?
Writing a plugin is CLN's superpower. Example of a minimal Python plugin that logs all incoming payments and adds a custom RPC method:
#!/usr/bin/env python3
# payment_logger_plugin.py
from pyln.client import Plugin
plugin = Plugin()
@plugin.subscribe("invoice_payment")
def on_payment(invoice_payment, **kwargs):
"""Called on each successful incoming payment"""
label = invoice_payment.get("label")
amount_msat = invoice_payment.get("msat")
preimage = invoice_payment.get("preimage")
plugin.log(f"Payment received: label={label}, amount={amount_msat}msat")
notify_webhook(label, amount_msat)
@plugin.method("my_custom_method")
def custom_method(plugin, some_param, **kwargs):
"""Adds a new RPC method to CLN"""
return {"result": f"Processed: {some_param}"}
plugin.run()
Connect the plugin by adding plugin=/path/to/payment_logger_plugin.py to your config. Plugins using subscribe("invoice_payment") receive events without polling — this is the correct pattern for real-time payment processing.
Hook: Interceptor for Payments
For advanced cases (rate limiting, fraud detection) — the htlc_accepted hook:
@plugin.hook("htlc_accepted")
def on_htlc(onion, htlc, **kwargs):
"""Intercepts incoming HTLC before acceptance"""
amount = htlc.get("amount_msat")
# Reject if amount too small (anti-spam)
if amount < 1000: # < 1 sat
return {"result": "fail", "failure_message": "4100"}
return {"result": "continue"}
Channel Management and Routing
# Open channel
funding = rpc.fundchannel(
id="03abc...@ip:port",
amount=500000, # 500k sat
announce=True, # public channel
minconf=1, # minimum confirmations for funding tx
)
# List channels with balances
channels = rpc.listpeerchannels()
for ch in channels["channels"]:
print(f"Channel {ch['short_channel_id']}: local={ch['to_us_msat']}msat, remote={ch['total_msat'] - ch['to_us_msat']}msat")
# Send payment
payment = rpc.pay(bolt11="lnbc...")
print(f"Status: {payment['status']}, preimage: {payment.get('payment_preimage')}")
CLN vs LND: Practical Comparison
| Aspect | CLN | LND |
|---|---|---|
| API | Unix socket JSON-RPC, clnrest plugin | gRPC + REST built-in |
| Extensibility | Plugins (any language) | Interceptors (gRPC) |
| Performance | Lower RAM footprint | Higher at scale |
| Documentation | Fewer examples | Rich documentation |
| Macaroons/auth | Runes | Macaroons |
| Watch-only mode | No | Yes |
CLN is better if you need custom plugins with non-standard logic, minimal footprint is important, or you already work with Blockstream infrastructure. Our clients save up to 40% on transaction fees compared to LND.
How Long Does CLN Integration Take?
We offer turnkey CLN integration:
- Audit of current infrastructure and architecture design
- Node deployment from scratch or connection to an existing one
- Python plugin development (full cycle: from subscribe to hook)
- clnrest setup for REST API with Rune authorization
- Payment flow integration with your system (ERP, CRM, website)
- API documentation and automation scripts
- Team training (1-2 days)
- 3 months of technical support after handover
Estimated timelines: from 3 days for basic integration (payment reception + webhook) to 2 weeks for a full custom plugin with channels and hooks. Get a consultation on CLN integration — we will calculate the exact cost and timeline.
What Guarantees Do We Provide?
- Over 5 years working with Lightning Network
- 30+ successful integrations in production (fintech, gambling, e-commerce)
- 10+ CLN nodes under management
- All contracts undergo code audit (linters, tests, code review)
- We guarantee 99.9% payment receipt stability
Learn more about Core Lightning in the official documentation. Order CLN plugin development — contact us for a project assessment.







