Files
lnd/docs/db_migration_guide.md
2025-10-27 11:55:07 -07:00

9.4 KiB

LND Database Upgrade Guide: A Two-Stage Migration for Node Operators

Table of Contents


Overview

The LND Database Upgrade process enables node operators to migrate from the legacy bbolt key-value store to modern SQLite or PostgreSQL backends—first in kvdb mode, then ultimately to a relational database format. This two-stage migration addresses long-standing performance bottlenecks, and lays the foundation for scalable, maintainable node operations.

This guide explains the migration path, backend trade-offs, subsystem readiness, and best practices for safely upgrading your LND database.


Operation Modes

The LND database upgrade operates in two sequential stages, each with distinct tooling and implications:

flowchart TD
    %% 1. Define all nodes
    Bbolt["Bbolt (kvdb)"]
    SQLite["SQLite (kvdb)"]
    Postgres["Postgres (kvdb)"]
    
    M1_Sqlite["Migration #1 (lnd v0.19)<br>Invoices"]
    M2_Sqlite["Migration #2 (lnd v0.20)<br>Graph"]
    M3_Sqlite["Migration #3 (lnd v0.21)<br>Payments"]

    M1_Postgres["Migration #1 (lnd v0.19)<br>Invoices"]
    M2_Postgres["Migration #2 (lnd v0.20)<br>Graph"]
    M3_Postgres["Migration #3 (lnd v0.21)<br>Payments"]

    %% 2. Define all links (within and between graphs)
    Bbolt --> SQLite
    Bbolt --> Postgres
    
    SQLite --> M1_Sqlite
    M1_Sqlite --> M2_Sqlite
    M2_Sqlite --> M3_Sqlite

    Postgres --> M1_Postgres
    M1_Postgres --> M2_Postgres
    M2_Postgres --> M3_Postgres

    %% 3. Group nodes into subgraphs
    subgraph "Step 1: Migration via lndinit"
        Bbolt
        SQLite
        Postgres
    end

    subgraph "Step 2: Migration within lnd"
        M1_Sqlite
        M2_Sqlite
        M3_Sqlite
        M1_Postgres
        M2_Postgres
        M3_Postgres
    end

    %% 4. Apply Styles
    %% Define classes with explicit dark text color (#333)
    classDef bboltNode fill:#e2e3e5,stroke:#383d41,color:#333
    classDef sqliteNode fill:#d4edda,stroke:#155724,color:#333
    classDef postgresNode fill:#cce5ff,stroke:#004085,color:#333

    %% Apply classes to nodes
    class Bbolt bboltNode
    class SQLite,M1_Sqlite,M2_Sqlite,M3_Sqlite sqliteNode
    class Postgres,M1_Postgres,M2_Postgres,M3_Postgres postgresNode
  • Stage 1: Migrate from bbolt to a SQL-based kvdb backend using the lndinit tool.
  • Stage 2: Incrementally migrate subsystem data (invoices, graph, payments, etc.) from kvdb to SQL native relational tables as support becomes available.

Stage 1: Migration from bbolt to SQLite/Postgres (kvdb)

LND cannot run with mixed backends, so all users must first leave bbolt behind. This stage uses the lndinit utility to perform an offline migration.

Choosing Your Target Backend

Backend Performance (in kvdb mode) Default in LND? Long-Term Viability
Postgres Mediocre No
SQLite Good Yes (future)

💡 Recommendation: Unless you require Postgres for infrastructure reasons, migrate to SQLite kvdb as your backend.

Postgres kvdb Migration

A migration script is available via lndinit:

  • Postgres migration script
  • Caveat: Users report degraded performance in kvdb mode. Only proceed if you plan to immediately follow with Stage 2 to migrate the available data stores to relational DB. This will mitigate the poor Postgres performance on kvdb.

SQLite kvdb Migration


Stage 2: Migration from kvdb to Relational Database

This stage unlocks true SQL performance by restructuring data into relational tables. Migration is per-subsystem and incremental.

Subsystem Readiness

Subsystem Relational Backend Migration Script Status
Invoices Available Available with v0.19
Graph Available Available with v0.20
Payments 🚧 In Progress Planned Targeted with v0.21
Btcwallet 🚧 In Progress Planned Targeted with v0.21
Forwarding History TBD TBD Future work

Known Limitations and Edge Cases

  • Single database engine required: LND requires a single consistent backend. You cannot run invoices in relational mode while graph remain in kvdb unless both are on the same SQL engine (e.g., SQLite).
  • Data loss risk: Always back up your data/ directory before migration.
  • Downtime required: Stage 1 requires LND to be offline. Stage 2 is done at startup, requiring a LND restart.
  • Postgres kvdb performance: Postgres performance on kvdb is sub-optimal. It is recommended to make the stage 2 migration immediately to avoid performance bottlenecks. Certain RPCs like listpayments may not perform well on Postgres if the node has a lot of payments data. If your node operation is heavy on payments and listpayments performance is critical for you, we'd recommend not doing any migration and wait till version 0.21.0 is released.
  • No migration path between SQL backend: Once migrated to either Postgres or SQLite, it is not possible to switch to the other, so choose your target backend carefully.

Best Practices for Node Operators

Choosing the Right Path

  • For most users: Choose SQLite, then migrate. Later, adopt relational backends subsystem-by-subsystem.
  • Enterprise/Postgres users: It is recommened to wait to start the migration until payments relational backend is ready, then perform Stage 1 + Stage 2 in quick succession.

Timing Your Migration

  • Perform migrations during low-activity periods.
  • Monitor LND release notes for relational DB support of different subsystems.

Validation

  1. Stop LND.
  2. Run migration with lndinit.
  3. Start LND with new backend flags, to execute stage 2 migrations.
  4. Validate node health: channels, balance, invoice/payment history.

Implementation Examples

Migrating to SQLite kvdb

# Stop LND
lnd --shutdown

# Backup
cp -r ~/.lnd ~/lnd-backup-$(date +%Y%m%d)

# Run migration (e.g. sqlite)
lndinit --debuglevel info migrate-db \
--source.bolt.data-dir ~/.lnd/data \
--dest.backend sqlite \
--dest.sqlite.data-dir ~/.lnd/data --network mainnet

# Start LND with SQLite backend
lnd --db.backend=sqlite

📝 Add db.backend=sqlite to your lnd.conf to make it persistent.

Migrating Invoices to Relational Backend

Once on LND v0.19+ with SQLite/Postgres:

# Ensure backend is set
echo "db.backend=sqlite" >> ~/.lnd/lnd.conf

# Start LND — invoice migration runs automatically
lnd

Check logs for:

Migrating invoices from kvdb to relational format...
Invoice migration completed successfully.

Future Improvements

The LND team is actively working on:

  • Payments relational backend and migration tooling (Stage 2)
  • Btcwallet relational backend and migration tooling (Stage 2)
  • Forwarding history relational schema (long-term)
  • Automatic detection of migration readiness in lnd

Node operators should monitor:


Conclusion

The LND database upgrade is a strategic two-stage process designed to eliminate bbolt performance limitations while ensuring data integrity and operational continuity.

By first migrating to SQLite/Postgres kvdb and then adopting relational backends incrementally, node operators can achieve significant performance gains—especially for payment-heavy workloads—without rushing into unstable configurations.

Choose your path wisely, back up rigorously, and stay informed. The future of LND is relational, and this guide ensures you get there safely.