Skip to main content
Dear Lago Community, We’re writing to inform you about important changes in Lago v1.45.0 that introduce wallet traceability — a feature that links outbound wallet transactions to their source inbound transactions, providing a full audit trail of credit consumption.

What are the changes?

Wallet Traceability

This version introduces wallet traceability — a system that tracks exactly which inbound (top-up) transactions fund each outbound (consumption) transaction. This enables:
  • Credit source visibility: Distinguishing when free (granted) vs. purchased credits are being consumed.
  • Full audit trail: Every outbound transaction records exactly which inbound transactions funded it and in what amounts.
  • Invoice breakdown: Invoices now show a breakdown of granted vs. purchased credit usage, enabling more accurate accounting and reporting.
  • New API endpoints: Query which inbound transactions funded a given outbound transaction, and vice versa.
Wallets created after upgrading to v1.45.0 are automatically traceable. However, existing wallets require a one-time backfill to compute the consumption history from their past transactions. This backfill is performed via a rake task described below.
Non-traceable wallets will continue to function for a few releases, but a future version will require all active wallets to be traceable. This migration is mandatory — we strongly recommend completing it as soon as possible.

What should self-hosted users do?

Cloud users do not need to follow these instructions as the migration will be performed by the Lago Team.
If you’re using a version below v1.44.0, please first follow the migration steps for v1.44.0. Only after completing those should you proceed to v1.45.0.

Migration Steps

1. Install Lago v1.45.0

Install the new version. Schema migrations (new tables and columns) will run automatically on startup.

2. Validate wallets (dry-run)

Open a shell on your API server and run the migration task in dry-run mode (the default):
You can scope the validation to a specific organization or limit the number of customers processed:
The available environment variables are: The dry-run performs a validation of all your wallets without modifying any data. It will output:
  • A progress bar showing validation progress.
  • The number of wallets that can be migrated automatically.
  • The number of problematic wallets with details about each issue.
  • A migration readiness percentage.
  • A CSV error log with all problematic wallets (written automatically to the tmp directory, see ERROR_LOG_FILE).
To override the default error log path:
If all wallets pass validation, you can skip directly to Step 4.
It is safe to run the backfill directly (Step 4) without running the dry-run first — the backfill also validates each wallet before migrating it and will roll back any customer with problematic wallets. The main purpose of the dry-run is to separate validation from migration, giving you the opportunity to review and fix problematic wallets upfront rather than discovering them during the backfill.

3. Fix or handle problematic wallets

Review the output from Step 2. For each problematic wallet, choose one of the following approaches based on the issue type (see the Troubleshooting section below for details):
  1. Fix the underlying data — Correct the transaction records so the wallet passes validation, then re-run Step 2 to confirm.
  2. Terminate and recreate — If the data is unrecoverable, terminate the wallet and create a new one (see Terminate and recreate).

4. Run the backfill

Once all wallets pass validation (or have been handled), run the same task with DRY_RUN=false:
As with the dry-run, you can scope the backfill:
This task:
  • Displays a progress bar showing backfill progress.
  • Computes and populates remaining_amount_cents for all inbound transactions.
  • Creates wallet_transaction_consumptions records linking inbound and outbound transactions.
  • Sets traceable = true on each successfully migrated wallet.
If a wallet has data inconsistencies (e.g., outbound transactions that cannot be fully consumed by available inbound transactions), the backfill will roll back all wallets for that customer and record the error, then continue processing other customers. All failures are reported in the summary output. Failed customers’ wallets will remain non-traceable and can be retried after fixing the underlying data. Always run the dry-run validation (Step 2) first to identify and fix issues before backfilling.
The backfill is safe to run multiple times. It acquires customer-level advisory locks and processes each customer’s wallets atomically, so it can be safely run while the application is serving traffic.
Monitor the task’s progress bar and verify completion by checking that all active wallets have traceable = true.

Scaling the migration with parallel processes

For most installations, a single process is fast enough — parallelization is only worth considering if you have hundreds of thousands of customers with wallets to migrate. We recommend starting with a smaller subset (e.g., LIMIT=1000) to get a feel for how long the migration takes, then extrapolating from there. There are two ways to parallelize the migration: Multi-threading (THREAD_COUNT) runs multiple threads within a single process. Due to Ruby’s Global VM Lock (GVL), this primarily helps when the bottleneck is database I/O wait time and may not significantly improve performance for CPU-bound workloads. Multiple processes with CURSOR + LIMIT is the recommended approach for large datasets. By splitting the customer space into non-overlapping windows, you can run several independent processes in parallel — each handling a different slice. This sidesteps the GVL entirely and scales linearly with the number of processes. To set this up, you simple launch the first process to discover the next cursor, then launch additional processes with the provided cursor to split the workload:
The same goes for the backfill:
Re-running the same CURSOR + LIMIT combination is safe but not recommended, as it will not produce the same result. If you need to re-run, start from the beginning without a CURSOR and continue with the cursors printed by each run.

Troubleshooting: Wallets that cannot be migrated

The validation task may flag wallets with data inconsistencies caused by historical bugs. Below are the known issue types and recommended resolutions.

Reconcilable issues

These issues can be fixed by updating the data directly in the database, then re-running the validation.
When fixing wallet balances, you may also need to update related attributes such as credits_balance and credits_ongoing_balance to keep the wallet consistent. If this level of manual correction is not acceptable, it is preferable to terminate the wallet and recreate it instead (see Terminate and recreate).

Non-reconcilable issues

These issues cannot be automatically reconciled due to historical data corruption. The wallet must be terminated and recreated (see Terminate and recreate).

Terminate and recreate escape hatch

Terminated wallets are ignored by the migration task and all traceability operations. It is safe to leave non-traceable wallets in a terminated state — active wallets will still fully benefit from traceability. If a wallet cannot be reconciled due to data issues, the recommended approach is:
  1. Terminate the problematic wallet.
  2. Create a new wallet for the customer.
  3. Top up the new wallet with the correct balance.
  4. The new wallet will automatically be created as traceable — all future transactions will have full consumption tracking from the start.
Wallets created after installing v1.45.0 are automatically traceable — they do not need to be backfilled. The migration task only applies to wallets that existed before the upgrade.
If the customer has a grace period configured, any draft invoice will automatically recompute prepaid credit amounts upon finalization — no special handling is needed.For customers without a grace period, any in-flight invoice generated between the termination of the old wallet and the creation of the new one may not correctly reflect prepaid credit usage. We recommend enabling a grace period on affected customers before performing the terminate-and-recreate procedure to avoid this issue.

Timeline

We recommend performing this migration as soon as possible after the release of v1.45.0. Non-traceable wallets will continue to function for a few releases, but support for non-traceable wallets will be removed in a future version. All active wallets will be required to be traceable, making this migration mandatory.

Get Involved

If you have any questions or encounter issues during the migration, please reach out to us via the Slack community. Our team is here to help you through this transition. Thanks for your understanding and continued support. The Lago Team