# How Adaptive Battery Optimization Works in BitChat's BLE Service Duty Cycling

> Discover how BitChat's BLE service duty cycling optimizes battery usage by dynamically adjusting intervals based on traffic, node connections, and power levels. Maintain connectivity efficiently.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: deep-dive
- Published: 2026-07-27

---

**BitChat's BLE transport dynamically adjusts scanning and advertising intervals based on real-time mesh traffic, node degree, and battery level to minimize power consumption while maintaining connectivity.**

BitChat is an open-source mesh messaging application that relies on Bluetooth Low Energy (BLE) for peer-to-peer communication. To prevent excessive battery drain during idle periods, the codebase implements an intelligent duty-cycling system within [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift) that continuously adapts to network conditions and device state.

## Core Mechanisms of Adaptive Duty Cycling

The adaptive battery optimization in BitChat operates through five interconnected mechanisms that balance connectivity against power consumption.

### High-Degree Threshold and Probabilistic Relays

BitChat uses a **configurable high-degree threshold** defined in [`TransportConfig.swift`](https://github.com/permissionlesstech/bitchat/blob/main/TransportConfig.swift) to identify nodes with many neighboring peers.

```swift
// TransportConfig.swift - Line 10
static var bleHighDegreeThreshold: Int = 6

```

When a node's neighbor count exceeds this threshold, it enters a **probabilistic relay mode**. This mode applies **adaptive TTL (Time-To-Live)** values to packets, shortening packet lifespans to reduce unnecessary retransmissions. According to the implementation in [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift) at line 232, this adaptation prevents high-degree nodes from wasting energy relaying stale packets throughout the mesh.

### Traffic-Based Scan Planning

The `BLEScanDutyPolicy` class (implemented in [`BLEScanDutyPolicy.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEScanDutyPolicy.swift)) monitors **recent traffic timestamps** stored by the BLE service to determine optimal scan frequencies.

When the mesh has been quiet, the policy returns a low-frequency scan plan. During traffic spikes, it returns higher-frequency plans. As referenced at line 6997 of [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift), this traffic-aware approach ensures BLE scanning only consumes power when the network is active.

```swift
// Simplified logic from BLEScanDutyPolicy.swift
struct BLEScanDutyPolicy {
    static func plan(recentTraffic: [Date]) -> ScanPlan {
        let idleDuration = Date().timeIntervalSince(recentTraffic.last ?? .distantPast)
        
        if idleDuration > 30 * 60 {          // >30 min idle
            return ScanPlan(interval: 300, window: 5)   // 5 min interval, 5s window
        } else if idleDuration > 5 * 60 {    // moderate activity
            return ScanPlan(interval: 30, window: 10)  // 30s interval, 10s window
        } else {                              // active traffic
            return ScanPlan(interval: 5, window: 20)   // 5s interval, 20s window
        }
    }
}

```

### Back-Pressure Buffer Management

The system monitors the **BLEOutboundWriteBuffer** to detect congestion. As documented in [`ARCHITECTURE_V2.md`](https://github.com/permissionlesstech/bitchat/blob/main/ARCHITECTURE_V2.md) at line 46, when the outbound buffer accumulates pending packets, the scan duty cycle automatically increases to clear the backlog faster. Conversely, when the buffer remains empty, the duty cycle reduces to conserve power.

### Battery-Sensitive Scheduling

During initialization, `BLEService` checks the device's battery level using `UIDevice.current.batteryLevel`. When the battery falls below a safe threshold, the service forces the scan plan to its most conservative setting. This ensures that BLE activity does not drain the battery excessively during low-power states.

### Adaptive TTL Implementation

High-degree nodes implement **adaptive TTL** to limit packet propagation distances. By reducing TTL values when connected to many peers, the system prevents energy-intensive network flooding. This mechanism is particularly important for devices acting as mesh relays in dense network environments.

## Practical Implementation Examples

To initialize a BLE service with adaptive duty cycling:

```swift
import CoreBluetooth

let bleService = BLEService(
    config: TransportConfig(),
    scanDutyPolicy: BLEScanDutyPolicy()
)

// Trigger manual recalculation after battery level changes
bleService.updateDutyCycleIfNeeded()

```

Adjusting the high-degree threshold at runtime alters when probabilistic relaying activates:

```swift
// Make adaptive relay trigger later (more conservative)
TransportConfig.bleHighDegreeThreshold = 8

// Make adaptive relay trigger earlier (more aggressive power saving)
TransportConfig.bleHighDegreeThreshold = 4

```

## Key Source Files

The following files contain the core adaptive battery optimization logic:

- **[`bitchat/Services/TransportConfig.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/TransportConfig.swift)** - Defines `bleHighDegreeThreshold` for node degree calculations
- **[`bitchat/Services/BLE/BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/BLE/BLEService.swift)** - Core implementation tracking traffic timestamps and applying duty cycles
- **[`bitchat/Services/BLE/BLEScanDutyPolicy.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Services/BLE/BLEScanDutyPolicy.swift)** - Algorithm for determining scan intervals based on recent activity
- **[`docs/ARCHITECTURE_V2.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/ARCHITECTURE_V2.md)** - Documentation explaining the back-pressure buffer and scheduling state separation

## Summary

BitChat's adaptive battery optimization works by:

- **Monitoring node degree** through `bleHighDegreeThreshold` to enable probabilistic relaying
- **Tracking traffic patterns** via `BLEScanDutyPolicy` to adjust scan intervals dynamically
- **Managing back-pressure** through outbound buffer monitoring to clear congestion efficiently
- **Respecting battery levels** by forcing conservative scan plans when power is low
- **Limiting packet propagation** using adaptive TTL to prevent unnecessary retransmissions

These mechanisms allow BitChat to maintain mesh connectivity while significantly reducing BLE power consumption during idle periods.

## Frequently Asked Questions

### How does BitChat detect when to switch between scan intervals?

BitChat's `BLEScanDutyPolicy` examines the timestamps of recent mesh traffic stored in `BLEService`. If no packets have been received for over 30 minutes, it switches to a 5-minute scan interval. If traffic arrives within 5 minutes, it uses aggressive 5-second intervals. This traffic-aware approach ensures the radio only activates when necessary.

### What happens when a BitChat node connects to many peers simultaneously?

When a node exceeds the `bleHighDegreeThreshold` (default 6 peers), it activates probabilistic relay mode. This mode applies shorter TTL values to packets and probabilistically drops relay requests, preventing the node from wasting energy broadcasting messages to an already well-connected neighborhood.

### Can developers adjust the battery optimization sensitivity?

Yes. Developers can modify `TransportConfig.bleHighDegreeThreshold` to change when high-degree mode activates, or implement custom `BLEScanDutyPolicy` classes with different idle timeout thresholds. The architecture in [`ARCHITECTURE_V2.md`](https://github.com/permissionlesstech/bitchat/blob/main/ARCHITECTURE_V2.md) specifically separates scheduling state from `BLEService` to enable such customizations.

### Does adaptive duty cycling affect message delivery reliability?

The system maintains reliability through **back-pressure monitoring**. When the `BLEOutboundWriteBuffer` detects pending messages, it temporarily increases scan frequency to ensure packets clear quickly. Additionally, the traffic detection algorithm responds rapidly to new activity, ramping up from 5-minute intervals to 5-second intervals within seconds of detecting incoming mesh traffic.