Problem
/api/info can take many seconds when the LSPS2 liquidity source (e.g. Megalith) is unreachable or rejects the request (LSPSResponseError). Observed in dev mode, where every info call blocks for seconds; the auto-unlock toggle appeared slow only because the settings screen awaits an info refetch after saving.
Cause
For the LDK backend, GetInfo (api/api.go) calls GetLiquiditySourceLsps2MinPaymentSizeMsat() / GetLiquiditySourceLsps2MaxPaymentSizeMsat(), which call fetchLsps2OpeningFeeParams (lnclient/ldk/ldk.go). That performs a synchronous RequestOpeningFeeParams() network round-trip to the LSP when the cache is stale, with several aggravating details:
- Failures are never cached — on error the function returns without setting
lsps2InfoFetchedAt, so the 60-minute cache never becomes valid and every subsequent info call re-attempts the network request and blocks until it fails. useInfo(poll) polls /api/info every 3s on some screens, so a failing LSP is also hammered with doomed requests.
- The mutex is held across the network call —
lsps2InfoMu is locked for the duration of RequestOpeningFeeParams(), so concurrent info calls serialize behind each other. The JIT invoice path (getLsps2MaxTotalOpeningFeeMsat) shares the same mutex, so invoice creation can queue behind a stuck info poll.
- The fetch happens even when JIT channels is disabled — the LSPS2 calls in
GetInfo are gated only on the backend being LDK, not on the JitChannelsEnabled setting (which is only consulted at invoice creation). With JIT channels turned off, /api/info still triggers wasteful LSP network requests.
No issues reported from production so far (this only bites while the LSP is failing/unreachable), so this is not urgent — but during an LSP outage the whole UI would feel sluggish, since nearly every screen touches /api/info.
Possible fixes
- Reconsider whether the LSPS2 min/max payment size data belongs in the info endpoint at all —
/api/info is called constantly and should stay cheap; a dedicated endpoint (or the existing channel/liquidity endpoints) may be a better home.
- Skip the LSPS2 fetch when JIT channels is disabled.
- If it stays: record the attempt time on failure and apply a short retry backoff (e.g. 1 minute) so a failing LSP costs one slow request per backoff window instead of one per call.
- Perform the network fetch outside the mutex (fetch first, then lock to store) so concurrent callers don't serialize.
🤖 Generated with Claude Code
Problem
/api/infocan take many seconds when the LSPS2 liquidity source (e.g. Megalith) is unreachable or rejects the request (LSPSResponseError). Observed in dev mode, where every info call blocks for seconds; the auto-unlock toggle appeared slow only because the settings screen awaits an info refetch after saving.Cause
For the LDK backend,
GetInfo(api/api.go) callsGetLiquiditySourceLsps2MinPaymentSizeMsat()/GetLiquiditySourceLsps2MaxPaymentSizeMsat(), which callfetchLsps2OpeningFeeParams(lnclient/ldk/ldk.go). That performs a synchronousRequestOpeningFeeParams()network round-trip to the LSP when the cache is stale, with several aggravating details:lsps2InfoFetchedAt, so the 60-minute cache never becomes valid and every subsequent info call re-attempts the network request and blocks until it fails.useInfo(poll)polls/api/infoevery 3s on some screens, so a failing LSP is also hammered with doomed requests.lsps2InfoMuis locked for the duration ofRequestOpeningFeeParams(), so concurrent info calls serialize behind each other. The JIT invoice path (getLsps2MaxTotalOpeningFeeMsat) shares the same mutex, so invoice creation can queue behind a stuck info poll.GetInfoare gated only on the backend being LDK, not on theJitChannelsEnabledsetting (which is only consulted at invoice creation). With JIT channels turned off,/api/infostill triggers wasteful LSP network requests.No issues reported from production so far (this only bites while the LSP is failing/unreachable), so this is not urgent — but during an LSP outage the whole UI would feel sluggish, since nearly every screen touches
/api/info.Possible fixes
/api/infois called constantly and should stay cheap; a dedicated endpoint (or the existing channel/liquidity endpoints) may be a better home.🤖 Generated with Claude Code