# How SpeedLimitController Manages Upload and Download Speed Limits in Motrix

> Discover how Motrix SpeedLimitController manages upload and download speed limits. It computes effective caps from settings, schedules, and network conditions, applying them every 60 seconds for optimal bandwidth control.

- Repository: [Dr_rOot/Motrix](https://github.com/agalwood/Motrix)
- Tags: how-to-guide
- Published: 2026-08-19

---

**The SpeedLimitController orchestrates bandwidth regulation by computing effective caps from user settings, schedule windows, and adaptive network conditions, then applies them to the download engine every 60 seconds.**

The `SpeedLimitController` in the Motrix download manager provides a rule-driven system for regulating network bandwidth. Located in [`src/core/speed-limit/speed-limit-controller.ts`](https://github.com/agalwood/Motrix/blob/main/src/core/speed-limit/speed-limit-controller.ts), this TypeScript class aggregates multiple speed limit sources—base configurations, scheduled alternatives, turtle mode, and adaptive network sensing—into a single effective profile applied to the underlying aria2 engine.

## Architecture of the Speed Limit System

### Core Dependencies and Settings Retrieval

The controller initializes with a `getSettings` callback that returns user-defined `SpeedLimitSettings` containing base, alt, auto, and turtle configurations. These settings define the raw bandwidth caps before any runtime logic is applied.

```typescript
const controller = new SpeedLimitController({
  getSettings: () => speedLimitStore.get(),
  applyLimits: async (profile) => engine.setSpeedLimits(profile),
  getEngineState: () => engine.state,
  emit: (ch, payload) => ipc.send(ch, payload),
  isVideoAppRunning: () => videoProbe.isRunning(),
})

```

## Computing Effective Upload and Download Caps

The controller delegates limit calculation to `computeEffectiveLimits` in [`src/core/speed-limit/effective-limits.ts`](https://github.com/agalwood/Motrix/blob/main/src/core/speed-limit/effective-limits.ts). This function evaluates multiple candidate caps and returns the most restrictive non-zero value.

### The Limit Selection Algorithm

The algorithm builds a list of candidate download and upload caps:

- **Base limits** are always included as the default ceiling.
- **Turtle mode** caps both directions to the minimum of base and alt limits when enabled.
- **Auto mode** adds alt limits when the current time falls within a schedule window (`withinWindow`) or when a video application is detected running.
- **Adaptive mode** inserts a head-room-adjusted cap derived from real-time network link speed measurements.

The helper function `minCap` selects the smallest non-zero value from this collection, treating `0` as "unlimited". This ensures the most restrictive active rule always takes precedence.

```typescript
const currentLimits = controller.getEffective()
console.log(`Download ≤ ${currentLimits.download} KiB/s, Upload ≤ ${currentLimits.upload} KiB/s`)

```

## Applying Limits to the Download Engine

When the engine reports `EngineState.Ready`, the controller invokes `applyLimits` with the computed `SpeedLimitProfile`. The controller tracks the last pushed profile in a `lastPushed` variable to avoid redundant updates.

If the new profile differs from the previous state, the controller emits a `SpeedLimitChanged` event containing the complete `SpeedLimitState`. This payload includes the turtle status, effective profile values, and the active reason for the limit, allowing UI components to display real-time feedback.

## Lifecycle Management and Periodic Enforcement

### Timer-Based Recomputation

The `start()` method creates a periodic timer using `SCHEDULE_TICK_MS = 60000` (60 seconds). This ensures schedule-based speed limit changes take effect without requiring user interaction, even if the system clock crosses a schedule boundary.

```typescript
// Start periodic enforcement
controller.start()

// Force recompute when engine becomes ready
engine.on('ready', () => controller.onEngineReady())

```

### Graceful Shutdown and State Invalidation

The `stop()` method halts the recomputation timer and increments an internal generation counter. This counter invalidates any pending asynchronous work, preventing race conditions when the controller shuts down or restarts.

The `onEngineReady()` hook forces an immediate limit push when the engine transitions to the Ready state, ensuring bandwidth restrictions apply as soon as the download backend becomes available.

## Determining the Active Limit Reason

For debugging and transparency, the private `reasonFor` method determines why a specific limit is active. It analyzes the current settings, time, and video application status to return one of the following reasons: *base*, *turtle*, *schedule*, *videoApp*, *adaptive*, or *none*.

This reason string becomes part of the emitted `SpeedLimitState`, allowing the Motrix interface to display informative labels like "Limited by video detection" or "Turtle mode active" alongside the current speed cap values.

## Summary

- **Centralized calculation**: The `SpeedLimitController` in [`src/core/speed-limit/speed-limit-controller.ts`](https://github.com/agalwood/Motrix/blob/main/src/core/speed-limit/speed-limit-controller.ts) aggregates settings and delegates computation to `computeEffectiveLimits`.
- **Multi-source logic**: Effective caps derive from base settings, turtle mode, scheduled windows, video-app detection, and adaptive network sensing.
- **Conservative application**: The `minCap` helper enforces the most restrictive non-zero limit, treating zero as unlimited bandwidth.
- **Periodic enforcement**: A 60-second timer ensures schedule-based limits update automatically without user intervention.
- **State transparency**: The `reasonFor` method provides UI-friendly explanations for why specific limits are active.

## Frequently Asked Questions

### How often does SpeedLimitController update speed limits in Motrix?

The controller recomputes and applies limits every 60 seconds via a periodic timer initialized in the `start()` method with `SCHEDULE_TICK_MS = 60000`. Additionally, `onEngineReady()` forces an immediate update whenever the engine transitions to the Ready state.

### What happens when turtle mode is enabled?

When turtle mode is active, the controller caps both download and upload speeds to the minimum of the base and alternative (alt) limits. This is calculated in `computeEffectiveLimits` by comparing the two values and selecting the smaller non-zero cap.

### Why does my speed limit show as "unlimited" when I set it to zero?

The `minCap` helper function in [`src/core/speed-limit/effective-limits.ts`](https://github.com/agalwood/Motrix/blob/main/src/core/speed-limit/effective-limits.ts) treats `0` as representing unlimited bandwidth. When collecting candidate caps, zero values are excluded from the minimum calculation, allowing higher non-zero limits or truly unlimited speeds to take effect.

### How does Motrix detect when to apply schedule-based speed limits?

The `computeEffectiveLimits` function checks if the current time falls within a defined schedule window using the `withinWindow` predicate. When auto mode is enabled and the time matches a scheduled window—or when a video application is running—the alternative (alt) limits are added to the candidate pool for consideration.