Skip to content

fix(filter): suppress subscription renewal in background mode#1304

Open
xAlisher wants to merge 2 commits into
logos-messaging:masterfrom
xAlisher:fix/background-mode-filter-subscriptions
Open

fix(filter): suppress subscription renewal in background mode#1304
xAlisher wants to merge 2 commits into
logos-messaging:masterfrom
xAlisher:fix/background-mode-filter-subscriptions

Conversation

@xAlisher

@xAlisher xAlisher commented Jun 2, 2026

Copy link
Copy Markdown

Problem

On mobile (Android/iOS), Waku filter subscriptions have a relay-side TTL of ~13.5 minutes (observed). When a subscription expires, the closing channel fires in subscriptionLoop, checkAndResubscribe runs, and a new wf.Subscribe() RPC is issued — waking the LTE modem from RRC Idle.

With a loaded account (50 contacts, 3 communities) this produces ~4.4 radio wakeups/hr overnight: ~144 mAh/hr of battery drain with the screen locked. Measured via dumpsys batterystats --charged on Android 13 (status-im/status-app#21045, T5b soak).

Fix

Adds backgroundMode atomic.Bool to Sub + SetBackgroundMode(bool) on Sub and FilterManager.

background=true (screen locked):

  • 5s health-check ticker skipped
  • Expired subscription IDs dropped without resubscription — no network I/O

background=false (foreground return):

  • Immediately sends to closing to trigger resubscription
  • All expired filters reconnect in one burst

Impact

Before After
Radio wakeups/hr (background) ~4.4 0
Drain rate, loaded account, cellular ~144 mAh/hr ~5–10 mAh/hr (est.)
Foreground latency +1 reconnect burst on open

Messages sent while backgrounded are delivered via mailserver on foreground — not lost.

Usage

filterManager.SetBackgroundMode(true)   // on background
filterManager.SetBackgroundMode(false)  // on foreground — triggers resubscription

Companion status-go PR: status-im/status-go#7508

Adds backgroundMode to Sub and SetBackgroundMode(bool) to both Sub and
FilterManager. When background=true, subscriptionLoop skips the 5-second
health-check ticker and drops expired subscription IDs from the closing
channel without resubscribing. When background=false (foreground return),
a resubscription is immediately triggered for any expired filters.

Background context (status-im/status-app#21045):
On Android, each Waku filter subscription has a relay-side TTL (~13.5 min
observed). When it expires, the closing channel fires, checkAndResubscribe
runs, and a new wf.Subscribe() RPC wakes the LTE modem. With a loaded
account this happens every ~13.5 min overnight, producing a 55% radio
duty cycle (~144 mAh/hr) while the screen is locked.

With background mode active, no network I/O occurs during subscription
expiry. On foreground return, all expired filters are resubscribed in
one burst — the user sees a brief reconnect, then full message delivery.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
xAlisher added a commit to status-im/status-go that referenced this pull request Jun 2, 2026
R1 of battery-drain fix (#21045).

When the Android app is backgrounded, expiring light-client filter
subscriptions triggered wf.Subscribe() RPCs that woke the LTE radio.
This adds a background-mode gate at every layer of the call chain:

  Messenger.SetAppBackground
    → messaging.API.SetFilterBackgroundMode
    → transport.Transport.SetFilterBackgroundMode
    → Waku interface / gowaku.Waku
    → filterapi.FilterManager.SetBackgroundMode (go-waku)
    → filterapi.Sub.SetBackgroundMode (go-waku)

While backgrounded the subscriptionLoop's ticker and closing-channel
cases are suppressed; on foreground return a single resubscribe is
queued to catch any subscriptions that expired while idle.

go-waku changes: logos-messaging/logos-delivery-go#1304
go.mod replace directive: xAlisher/go-waku@ab4609ef

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
xAlisher added a commit to status-im/status-app that referenced this pull request Jun 2, 2026
Includes fix(filter): suppress Waku filter-subscription renewal in background
(R1 of #21045 battery-drain fix, logos-messaging/logos-delivery-go#1304)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FilterHealthCheckLoop fires every 1 min and sends a Waku protocol ping
to each subscribed filter peer. On Android, these pings queue up during
Doze and flush in maintenance windows (~15 min), keeping the LTE modem
at ~55-58% duty cycle even when the app is backgrounded.

This was the dominant radio wakeup source missed by the previous commit
(which only gated subscription renewal in subscriptionLoop). mag's
measurement on #21111 confirmed modem still 58% active post-R1.

Add backgroundMode atomic.Bool to WakuFilterLightNode with a
SetBackgroundMode(bool) method. FilterHealthCheckLoop skips PingPeers()
when backgrounded. FilterManager.SetBackgroundMode now cascades to both
layers: subscription renewal (api/filter) and health-check pings
(protocol/filter).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
xAlisher added a commit to status-im/status-go that referenced this pull request Jun 3, 2026
…sion)

Adds FilterHealthCheckLoop background guard — the dominant LTE radio
wakeup source (1-min pings to filter peers, batched by Doze into
~15-min windows at ~55% duty cycle).

go-waku change: logos-messaging/logos-delivery-go#1304

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@igor-sirotin igor-sirotin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TLDR; This change would silently make Status deaf after 5 minutes of being in backgroundMode.

Explaining the consequences

  1. There is indeed a TTL for subscriptions: it's 5 minutes here.

    • TTL is extended with either a SUBSCRIBE request, or PING, but both are blocked in this PR. If neither of these 2 is received within 5 minutes, the subscription is closed.
    • (not sure where ~13.5 minutes is coming from)
  2. If a subscription died for any other reasons (e.g. remote peer is down), we should resubscribe to other nodes.

    • Each subscription's health is currently checked once in 5 seconds. But this PR drops this logic in backgroundMode=true.

So after 5 minutes of backgroundMode=true, all connected nodes will expire the subscription, and we will silently ignore this. Effect: no incoming messages.

My suggestion is:

  1. Increase TTL in the fleet up to 30 minutes
  2. Keep PING working, but increase the period to 10 minutes.
  3. Keep the re-subscription logic.

Warning

Increasing a TTL should be consulted with AnonComms team, I'm not sure if it's a safe move.

"background mode"

I understand the intention, but I'm not sure I agree with the idea of "Background mode" in general.
Why is background mode more important than foreground? Why allow draining the battery when the app is opened?

We should look for a solution that can be always applicable.

I guess in background we could allow Status to have some delays in message delivery, but this would be implemented in a vey different way, and as a user I would expect messages to arrive instantly. And in any way, reliability should not be neglected.

Other comments

Please remove any mentions of UI/LTE and other app-level logic.
If we keep backgroundMode, then it could be mentioned once, as a use-case example. But in general, e.g. UI is not a concern of logos-delivery-go.

@jrainville jrainville left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Igor. This change would realistically make the message receiver not work.

I think we could skip this change for now and keep only the status-go change of not doing store node calls.

The changes here have a too big chance of introducing a regression where push notifications would just not work, which defeats the whole purpose of the background service.

jrainville pushed a commit to status-im/status-go that referenced this pull request Jun 3, 2026
R1 of battery-drain fix (#21045).

When the Android app is backgrounded, expiring light-client filter
subscriptions triggered wf.Subscribe() RPCs that woke the LTE radio.
This adds a background-mode gate at every layer of the call chain:

  Messenger.SetAppBackground
    → messaging.API.SetFilterBackgroundMode
    → transport.Transport.SetFilterBackgroundMode
    → Waku interface / gowaku.Waku
    → filterapi.FilterManager.SetBackgroundMode (go-waku)
    → filterapi.Sub.SetBackgroundMode (go-waku)

While backgrounded the subscriptionLoop's ticker and closing-channel
cases are suppressed; on foreground return a single resubscribe is
queued to catch any subscriptions that expired while idle.

go-waku changes: logos-messaging/logos-delivery-go#1304
go.mod replace directive: xAlisher/go-waku@ab4609ef

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jrainville pushed a commit to status-im/status-go that referenced this pull request Jun 3, 2026
…sion)

Adds FilterHealthCheckLoop background guard — the dominant LTE radio
wakeup source (1-min pings to filter peers, batched by Doze into
~15-min windows at ~55% duty cycle).

go-waku change: logos-messaging/logos-delivery-go#1304

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants