Skip to content

Background Tasks ​

Invoice listeners, background tasks, and async patterns for LNbits extensions.

LNbits runs several async background tasks for payment processing and maintenance.

Core tasks ​

TaskIntervalPurpose
Invoice listenerContinuousWatches for paid invoices from the funding source
Payment checker30 minutesRe-checks pending payments for status updates
Exchange ratesPeriodicFetches fiat exchange rates
Audit queueContinuousProcesses audit log entries
Notification queueContinuousSends email/push notifications
Webhook processorOn eventCalls webhook URLs for paid invoices

Invoice listeners ​

Extensions can register listeners to react to incoming payments:

python
import asyncio
from lnbits.tasks import register_invoice_listener

async def wait_for_paid_invoices():
    invoice_queue = asyncio.Queue()
    register_invoice_listener(invoice_queue, "ext_my_extension")

    while True:
        payment = await invoice_queue.get()
        await on_invoice_paid(payment)

async def on_invoice_paid(payment):
    # Filter by extension tag
    if payment.extra.get("tag") != "my_extension":
        return

    # Process the payment
    item_id = payment.extra.get("item_id")
    await mark_item_paid(item_id)

Registering startup tasks ​

In your extension's __init__.py:

python
def my_extension_start():
    """Called when the extension loads."""
    from lnbits.tasks import create_permanent_task
    create_permanent_task(wait_for_paid_invoices)

def my_extension_stop():
    """Called when the extension is disabled."""
    # Cleanup if needed
    pass

Task patterns ​

Periodic task ​

python
async def periodic_cleanup():
    while True:
        await cleanup_expired_items()
        await asyncio.sleep(3600)  # Every hour

Event-driven task ​

python
async def process_queue():
    while True:
        item = await my_queue.get()
        try:
            await process(item)
        except Exception as e:
            logger.error(f"Failed to process: {e}")

Best practices ​

  • Always wrap task bodies in try/except to prevent crashes
  • Use asyncio.sleep() between iterations to avoid busy-waiting
  • Filter payments by tag before processing - your listener receives ALL payments
  • Log errors but don't re-raise - crashed tasks don't restart automatically
  • Keep task handlers fast - slow handlers delay payment notifications