Architecture Comparison: bitSpire vs Traditional Lamassu
This document compares the bitSpire architecture — a Nostr-native Lightning ATM talking to LNbits over the nostr-native-transport — with the traditional lamassu-server + lamassu-machine architecture. The goal is to help an operator evaluating an open-source Lightning ATM stack understand what they're choosing between.
A note on prior art: bitSpire's hardware drivers and cash-flow state machine derive from Lamassu Industries AG's open-source lamassu-machine and lamassu-server projects up to and including the v8.1.5 release line (the last published under a fully-open license). Lamassu transitioned to a proprietary source-available license on 2024-01-26; bitSpire does not incorporate code from v8.1.6 or later and is not affiliated with Lamassu Industries AG. See the Acknowledgements section of the top-level README.
Executive summary
| Aspect |
Traditional (lamassu-server ≤ v8.1.5) |
bitSpire |
| Software license |
AGPL-3.0 (v8.1.5); v8.1.6+ is proprietary SLA |
AGPL-3.0 |
| Communication |
Custom WebSocket + GraphQL over HTTPS |
Nostr kind-21000 events (NIP-01, NIP-44 v2) over a relay |
| Identity |
Server-issued client certs |
Nostr keypairs (nsec/npub) |
| Account system |
PostgreSQL + custom auth |
LNbits wallet auto-created from ATM's nostr pubkey |
| Payment protocol |
Direct LND RPC |
BOLT11 (cash-out) + LNURL-withdraw (cash-in) |
| Server infrastructure |
App server + DB + Admin UI |
A relay + an LNbits instance (both can be one container) |
| Wallet compatibility |
Any Lightning wallet (cash-out); custom flow for cash-in |
Any Lightning wallet (BOLT11 + LNURL-withdraw — both widely supported) |
| State location |
Centralized in PostgreSQL |
Distributed: LNbits holds Lightning state, ATM holds session state |
Traditional architecture (lamassu-server / lamassu-machine, v8.1.5)
┌──────────────────┐ WebSocket ┌─────────────────────┐
│ ATM (kiosk) │◄──────────────────────────►│ lamassu-server │
│ lamassu-machine │ client-cert auth │ │
└──────────────────┘ │ ┌───────────────┐ │
│ │ PostgreSQL │ │
┌──────────────────┐ HTTPS │ └───────────────┘ │
│ Admin UI │◄──────────────────────────►│ │
│ (React SPA) │ GraphQL │ ┌───────────────┐ │
└──────────────────┘ │ │ LND │ │
│ └───────────────┘ │
┌──────────────────┐ │ │
│ Customer Wallet │◄── Lightning Invoice ──────│ ┌───────────────┐ │
│ (any LN wallet) │ │ │ Compliance │ │
└──────────────────┘ │ │ Services │ │
│ └───────────────┘ │
└─────────────────────┘
Components
| Component |
Description |
lamassu-server |
Node.js (Express + Apollo GraphQL) backend |
lamassu-machine |
Node.js kiosk app with hardware drivers |
| PostgreSQL |
Central DB for transactions, users, config |
| Admin UI |
React dashboard for fleet management |
| LND |
Lightning Network Daemon for payments |
Cash-out flow
- Machine boots, authenticates via client cert
- Server pushes config + state over WebSocket
- Customer initiates cash-out at machine
- Machine asks server for an invoice
- Server creates invoice via LND, stores in PostgreSQL
- Customer pays the invoice
- Server polls LND, detects payment, updates DB
- Server notifies machine to dispense
- Compliance services log the transaction
Characteristics
- Centralized: all state in
lamassu-server's PostgreSQL
- Operator-managed: requires real infrastructure (server, DB, certs, monitoring)
- Tightly coupled: machine doesn't transact if server is unreachable
- Compliance-ready: KYC/AML hooks built in (relevant in regulated jurisdictions)
bitSpire architecture
┌──────────────────┐ ┌──────────────────┐
│ ATM (kiosk) │ │ Customer wallet │
│ npub_atm │ │ (any LN wallet) │
└────────┬─────────┘ └────────┬─────────┘
│ kind-21000 │
│ NIP-44 v2 encrypted │ BOLT11
▼ │ LNURL-withdraw
┌───────────────────────────────┐ │
│ Nostr Relay │ │
│ (LNbits' bundled │ │
│ nostrrelay extension, or │ │
│ any standalone relay) │ │
└────────────────┬──────────────┘ │
│ │
│ kind-21000 RPC + push │
▼ │
┌───────────────────────┐ ◄──────────────────────┘
│ LNbits │ BOLT11 settle / LNURLw redeem
│ ┌──────────────────┐ │
│ │ FakeWallet (dev) │ │
│ │ or LND/CLN/etc. │ │
│ └──────────────────┘ │
└───────────────────────┘
Components
| Component |
Description |
| Nostr relay |
Message broker. In the dev compose, this is LNbits's bundled nostrrelay extension at ws://<host>:5001/nostrrelay/test. Production can use any standalone relay both peers subscribe to |
| LNbits |
Lightning wallet platform; runs the nostr-native-transport branch. Auto-creates a wallet on first contact from any nostr pubkey |
| ATM machine |
Electron + Vue 3 kiosk identified by its npub. Signing key IS the credential to LNbits |
| Customer wallet |
Any LN wallet that handles BOLT11 (cash-out) and LNURL-withdraw (cash-in) — most do |
Cash-out flow (customer pays ATM, gets cash)
- ATM publishes a kind-21000 event to LNbits:
{rpc_name: "create_invoice", body: {amount: <sats>, memo: "..."}}
- LNbits replies on the same relay with the BOLT11 invoice
- ATM displays the BOLT11 as a QR
- Customer scans, pays from any LN wallet
- LNbits's Lightning backend (FakeWallet / LND / CLN / etc.) settles the payment
- LNbits pushes a kind-21000 settlement event to the ATM, filtered by
payment_hash
- ATM dispenses cash
Cash-in flow (customer hands ATM cash, gets sats)
- ATM publishes
lnurlw_create_link (kind-21000) to LNbits with {uses: 1, max_withdrawable: <sats>}
- LNbits replies with a
WithdrawLink carrying a lnurl field already populated from settings.lnbits_baseurl (per aiolabs/withdraw#1 / e9d911e)
- ATM displays the LNURL as a QR (uppercased per BOLT/LNURL convention)
- Customer scans with any LNURL-withdraw-capable wallet, redeems it
- LNbits settles the withdrawal via its Lightning backend
- LNbits pushes a kind-21000 settlement event to the ATM, filtered by
tag="withdraw" + link_id
- ATM marks the session complete (cash already physically accepted earlier in the flow)
Characteristics
- Decentralized message layer: any nostr relay works, no proprietary protocol
- No admin tokens on the kiosk: the ATM's signing key IS the credential — there are no HTTP API tokens or client certs to leak. LNbits derives the calling identity from the event signature.
- Loose coupling: ATM and LNbits don't need to share a network segment; only a relay both reach
- Privacy-first: no central transaction logs unless the operator builds them. LNbits stores its own ledger, but bitSpire writes no user-identifying data anywhere on its side.
Detailed comparison
1. Infrastructure requirements
| Requirement |
Traditional |
bitSpire |
| Server hardware |
Dedicated server (4+ GB RAM, SSD) |
An LNbits instance (1 GB RAM is plenty in production) |
| Database |
PostgreSQL (operator managed) |
LNbits's SQLite (or its configured DB; LNbits manages it) |
| Client TLS |
Required (client certs per machine) |
Not required (signature-based auth over a nostr relay) |
| Domain |
Required |
Optional (only if exposing LNbits HTTP for LNURL redemption from the public internet) |
| Static IP |
Recommended |
Not required |
| Firewall |
Multiple inbound ports |
Outbound WebSocket to a relay; inbound only on the LNbits HTTP port for LNURL callbacks |
Edge: bitSpire. A single-container LNbits with FakeWallet is enough for an operator to evaluate the whole stack end-to-end.
2. Security model
| Aspect |
Traditional |
bitSpire |
| Machine auth |
Client certificates |
Nostr signing key |
| Transport security |
TLS |
NIP-44 v2 (XChaCha20 + HMAC-SHA256) |
| Compromise scope |
Server breach exposes all machines |
One machine's nsec compromises only that machine |
| Key storage |
Server manages |
Machine manages its own keys (/var/lib/bitspire/.env, mode 0600) |
| Revocation |
CA-style cert revocation |
Operator can stop honoring a pubkey at the LNbits layer; no fleet-wide blast radius |
Edge: bitSpire. No central authority that, if compromised, exposes the whole fleet. Per-machine compromise stays contained.
3. Payment flow
| Aspect |
Traditional |
bitSpire |
| Invoice creation |
Server creates via LND |
LNbits creates via its Lightning backend, returned over kind-21000 |
| Payment detection |
Server polls LND |
LNbits pushes a settlement event over kind-21000 (subscribe_payments filtered by payment_hash) |
| Cash-in detection |
Custom flow |
LNbits pushes a tag="withdraw" + link_id event when the LNURL is redeemed |
| Wallet compatibility |
Any BOLT11 wallet |
Any BOLT11 wallet (cash-out) + any LNURL-withdraw wallet (cash-in) |
| Offline capability |
None |
Cashu ecash (placeholder package, not yet wired) |
Tied. Both architectures end up using BOLT11 + LNURL-withdraw at the customer-wallet boundary. The difference is on the ATM side: traditional polls a server it owns; bitSpire subscribes to a push channel on a wallet it shares with anyone who can reach the relay.
4. Operator experience
| Aspect |
Traditional |
bitSpire |
| Setup time |
Hours (provision server, DB, TLS, cert each machine) |
Minutes (run an LNbits instance + a relay; flash + provision each ATM) |
| Maintenance |
DB backups, server updates, monitoring |
Update LNbits + the bitSpire ATMs (the latter auto-upgrades from the dev branch nightly) |
| Fleet management |
Mature Admin UI |
Per-ATM journalctl; centralized dashboard is planned, not built |
| Transaction history |
PostgreSQL queries |
Per-ATM /var/lib/bitspire/state.db (SQLite); operator-side aggregation is on them to build |
| Configuration |
Server-pushed |
Per-ATM .env written via provision-atm.sh |
Mixed. Traditional has mature operator tooling. bitSpire is simpler to stand up but the fleet-management story is currently "ssh + scripts" rather than a UI.
5. Customer experience
| Aspect |
Traditional |
bitSpire |
| Cash-out |
Scan BOLT11, pay |
Scan BOLT11, pay |
| Cash-in |
Varies by deployment (LNURL-withdraw common, sometimes custom) |
Scan LNURL-withdraw QR, redeem |
| Wallet requirements |
Any LN wallet for cash-out |
Any LN wallet for cash-out + any LNURL-w wallet for cash-in |
| Account required |
Sometimes (compliance) |
Never |
| Transaction speed |
~10 seconds |
~3-5 seconds (push-based; no server polling delay) |
Tied on protocol; slight edge to bitSpire on speed because LNbits push events skip the polling cycle that traditional setups have between LND and the application server.
6. Compliance & regulation
| Aspect |
Traditional |
bitSpire |
| KYC integration |
Built-in |
Not included |
| Transaction logs |
PostgreSQL (server) |
Per-ATM SQLite + whatever LNbits records on its side |
| Audit trail |
Comprehensive |
Operator-defined; LNbits's ledger is the canonical Lightning-side record |
| Reporting |
Admin UI exports |
Custom tooling needed |
| Regulatory fit |
Designed for KYC/AML jurisdictions |
Privacy-first design; suits jurisdictions without identity-collection requirements |
Edge: Traditional if you need built-in compliance. bitSpire targets KYC-free operation; operators in regulated jurisdictions would need to add compliance hooks themselves.
7. Resilience & availability
| Aspect |
Traditional |
bitSpire |
| Server down |
All machines stop transacting |
Machines stop transacting if LNbits is down; relay outage means RPCs hang |
| Network partition |
Transactions fail |
Can connect to multiple relays for failover |
| Database corruption |
Catastrophic (cascading impact across fleet) |
LNbits-side issue affects only the affected operator's wallet; per-ATM SQLite is local and independent |
| Recovery |
Restore from backup |
LNbits-side restore is its concern; ATMs come back up clean by re-reading .env |
| Geographic distribution |
Single server |
LNbits can be regional; relays can be anywhere |
Edge: bitSpire for blast-radius reasons. LNbits-side failures are no worse than lamassu-server-side failures, but bitSpire's per-ATM state is genuinely isolated.
8. Development & extensibility
| Aspect |
Traditional |
bitSpire |
| Codebase |
Large monolith (lamassu-server is hundreds of files) |
Modular workspace; ATM, transport client, HAL, state machine are separate packages |
| Protocol |
Custom WebSocket schema |
NIP-01 + NIP-44 v2 + a thin documented kind-21000 envelope |
| Third-party integration |
Custom API needed |
Any nostr/Lightning client can talk to LNbits over the transport |
| Community |
Lamassu operators (and ex-operators after the license change) |
Nostr + Bitcoin ecosystem; LNbits community |
| Forkability |
Complex (server + machine are coupled) |
Straightforward (replace any one package without touching the others) |
Edge: bitSpire. Open protocols mean a wider ecosystem of compatible clients, wallets, and tools.
When to choose what
Choose bitSpire if
- You operate in a jurisdiction without mandatory KYC/AML
- You want minimal infrastructure
- You value customer privacy (no PII collection, no central server-side ledger of who-paid-what)
- You're comfortable with emerging tooling (no admin UI yet)
- You want a license that stays open (AGPL-3.0)
Stick with lamassu-server v8.1.5 if
- You need built-in compliance features
- You need a mature admin dashboard today
- You have existing infrastructure investment in PostgreSQL + LND tooling
- You're comfortable being on a code line that no longer receives upstream updates (v8.1.5 is the last open release; bug fixes in v8.1.6+ are paid-license-only)
Choose Lamassu's current commercial offering if
- You want vendor support, official updates, and a commercial SLA
- You're willing to pay the per-machine subscription
- You operate in a regulated jurisdiction where KYC tooling matters
This last option is outside the scope of this document — see lamassu.is for their current commercial terms.
Trade-offs & honest assessment
Where bitSpire excels
- Simplicity — LNbits + a relay is a much smaller surface than a stateful application server + DB + admin tooling
- Privacy — no central transaction logs by design
- Resilience — no single point of failure on the ATM side; LNbits is replaceable
- Interoperability — works with any BOLT11 / LNURL-withdraw wallet
- Speed — push-based settlement detection skips the LND-poll cycle
- Cost — no Lamassu license fees; no commercial admin-server hosting
Where traditional (lamassu-server ≤ v8.1.5) is still better
- Compliance — built-in KYC/AML if your jurisdiction requires it
- Tooling — mature admin dashboard, fleet management, transaction reporting
- Maturity — battle-tested in production over many years
- Documentation — established support channels for operators (community-maintained for v8.1.5; commercial for v8.1.6+)
Current limitations of bitSpire
| Limitation |
Status |
Mitigation |
| No fleet dashboard |
Planned, not built |
Per-ATM journalctl + custom scripts |
| Limited transaction reporting |
SQLite per ATM |
Aggregate via operator-side ETL if needed |
| No offline mode |
@bitSpire/cashu is a placeholder |
Requires LNbits connectivity currently |
| Smaller operator community |
Growing |
This doc + the README walkthrough |
Further reading