Lets say there is a service in which users can have a few satoshis but are also able to deposite/withdraw satoshis by paying/sending a lightning invoice. Let us assume the service has some data store which tracks the account balance for the user:

What is the best practice architecture to know that the account balance needs to be updated?

I know there is the waitinvoice RPC-call in c-lightning which tracks the label of an invoice (which could be a user id + some other data). Still in a live application the site should update the balance once the invoice was paid. If however the user left the side and pays the invoice it still needs to work so there needs to be some bridge from the lightning node to the data store.

In withdrawing the situation gets even more critical since withdrawing can take some time and calls can occure concurrently balance needs to be locked or widthdraw calls have to by synchronized (which I guess ist not preferable)

So what kind of architectures / best practices are you using?

1 Answer 1


Both lnd and and c-lightning will include the payment request when notifying you of a payment. I personally used it through lightning charge with c-lightning for satoshis.place.

For each invoice generated (aka an "order"), I would keep a record of it in my database, along with the pixels to be drawn. Then when I see a payment coming in I go and fetch the order and process it.

I'll describe a simple architecture, lets break it down in 2 steps: deposits and withdrawals.


  • You're gonna need to maintain your own database of user accounts.
  • Include fields like: email, password, unique UUID and balance (you can add 2FA and API keys later).
  • Generate invoices for deposits, attach the UUID of the user that created it.
  • Increment the balance of the user when you see the payment come in, remember to do validation like checking amounts sent.


  • Have users give you invoices, maintain a table of withdrawal requests.
  • There might be situations where there isn't enough lightning capacity to pay a user. In this case you might want to provide the option to do off-chain withdrawals instead.
  • Off-chain withdrawals can be batched with other withdrawal requests, depending on usage of your service. I.e. withdrawals go out at the end of the day / week. This would optimize block space usage and lower any potential related fees paid per user.

I think what you are asking for is essentially software to run your own payment processor. Think about Strike and OpenNode but open-source?

I'm really interested in this topic. I really like the idea of stretching the idea of "Swiss Bank" in everyone's pocket to "PayPal / Stripe in everyone's node". I have some code I've been working on bbut it's still closed source, was intending to release it once MVP. If you're interested we could talk more about this during the Lightning Residency!

-- Koala

  • Great answer. However I was more asking about the complete architecture. How to isolate / secure services? What happens if the entire service needs to run on more than one lightning node / web server / database... I will edit my question a little bit Commented Oct 13, 2018 at 18:03
  • 1
    You want to split the application in a set of microservices (web, api, payment-watcher, db, etc) so you can provision and scale instances independently. Commented Oct 13, 2018 at 22:19
  • 1
    To handle multiple lightning nodes you'll probably want a "lightning manager" service which abstracts different ln node implementations, manages connection to ln nodes, triggers withdrawals and processes incoming payments, i.e. a POST request to API should be ok, this way the update logic stays in one place and it won't matter which instance your load balancer routes you to. You can use a message broker like redis to forward updates to the relevant client. Commented Oct 13, 2018 at 22:20
  • 1
    I recommend using Docker to compose your application and run it locally much in the same way it would be run eventually in production. Database depends on the engine you're using, whether you're sharding / replicating. You won't really need to worry about this until the app gets some serious traction - avoid premature optimisations ;) Same goes for the above really, it's better to minimise the feature set (i.e. only worry about doing it for 1 node) and gradually iterating rather than trying to do a lot at once. Commented Oct 13, 2018 at 22:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.