# What Is the Typical Time Slicing Threshold in Fre's Concurrent Mode?

> Discover Fre's concurrent mode time slicing threshold. Learn how its fixed 5 ms slice ensures UI responsiveness during intensive tasks and improves user experience.

- Repository: [frejs/fre](https://github.com/frejs/fre)
- Tags: internals
- Published: 2026-03-02

---

**Fre's concurrent mode uses a fixed 5 ms time-slicing threshold to determine when to yield control back to the browser, ensuring UI responsiveness during heavy computation.**

The Fre library (frejs/fre) implements a cooperative scheduling system inspired by React's concurrent features. At the heart of this system lies a hardcoded time-slicing threshold that dictates how long the scheduler can monopolize the main thread before yielding to the browser's event loop.

## Where the 5 ms Threshold Is Defined

In [`src/schedule.ts`](https://github.com/frejs/fre/blob/main/src/schedule.ts), the threshold is exported as a constant:

```typescript
const threshold: number = 5

```

This value represents milliseconds. The scheduler references this constant when initiating a new batch of work, calculating a deadline by adding the threshold to the current high-resolution timestamp.

## How the Scheduler Uses the Threshold

When work begins, the scheduler establishes a deadline in [`src/schedule.ts`](https://github.com/frejs/fre/blob/main/src/schedule.ts):

```typescript
deadline = getTime() + threshold

```

The `getTime()` function typically wraps `performance.now()`. As the scheduler processes tasks in a loop, it continuously checks `shouldYield()`, which returns `true` once `performance.now() >= deadline`. At this point, the scheduler pauses execution and schedules the remaining work for a subsequent frame using a microtask, `MessageChannel`, or `setTimeout` fallback.

## Why 5 ms? Balancing Throughput and Responsiveness

The 5 ms slice represents a compromise between two competing priorities:

- **Responsiveness**: Keeping slices below the 16 ms frame budget (60 fps) ensures the browser can handle user input, layout, and paint operations without jank.
- **Throughput**: A 5 ms window allows sufficient work to complete per slice, reducing the overhead of context switching and callback scheduling.

This value aligns with similar concurrent schedulers in the React ecosystem, providing predictable performance characteristics across devices.

## Working with the Time Slice in Practice

### Scheduling Heavy Computations

When breaking intensive work into chunks:

```typescript
import { schedule } from 'fre'

function processLargeDataset(index = 0) {
  const chunkSize = 100
  const end = Math.min(index + chunkSize, data.length)
  
  for (let i = index; i < end; i++) {
    processItem(data[i])
  }
  
  // Continue if work remains
  return end < data.length ? () => processLargeDataset(end) : undefined
}

schedule(processLargeDataset)

```

### Monitoring Yield Points

To observe when the scheduler yields:

```typescript
import { schedule, shouldYield } from 'fre'

let sliceCount = 0

schedule(() => {
  while (!shouldYield()) {
    // Perform work
    performUnitOfWork()
  }
  
  sliceCount++
  console.log(`Yielded after slice ${sliceCount} at ${performance.now()}ms`)
  
  // Return function to continue, or undefined to stop
  return hasMoreWork ? () => continueWork() : undefined
})

```

## Summary

- Fre's concurrent scheduler hardcodes a **5 ms time-slicing threshold** in [`src/schedule.ts`](https://github.com/frejs/fre/blob/main/src/schedule.ts).
- The scheduler calculates a deadline using `performance.now() + 5` at the start of each work phase.
- Work continues until `shouldYield()` detects the deadline has passed, at which point control returns to the browser.
- This 5 ms balance optimizes for both **60 fps responsiveness** and **efficient task throughput**.

## Frequently Asked Questions

### Why does Fre use a 5 ms threshold instead of a longer time slice?

Fre uses 5 ms to maintain compatibility with the browser's frame budget. At 60 frames per second, each frame has approximately 16.6 ms available. By yielding after 5 ms, Fre ensures sufficient time remains for the browser to handle layout, paint, and user input events, preventing interface jank while still making meaningful progress on background tasks.

### How can I monitor if my tasks are exceeding the time slice?

You can import `shouldYield` from `fre` and check its return value within your work loop. When `shouldYield()` returns `true`, the scheduler has exceeded the 5 ms deadline and will pause execution. Logging timestamps at these yield points allows you to measure actual slice duration and identify tasks that consistently overrun the threshold, indicating they need further decomposition.

### Does the threshold change based on device performance?

No, the threshold is a hardcoded constant (`const threshold: number = 5`) in [`src/schedule.ts`](https://github.com/frejs/fre/blob/main/src/schedule.ts). Unlike some adaptive schedulers that dynamically adjust time slices based on device capabilities or battery status, Fre uses a fixed 5 ms value across all environments. This provides predictable, deterministic behavior but means developers must ensure their work units fit within this universal constraint.

### Can I configure the time-slicing threshold in Fre?

Currently, Fre does not expose a public API to modify the threshold. The constant is defined internally in the scheduler module and is not exported or accepted as a configuration parameter. If you require different timing characteristics for specialized use cases, you would need to fork the repository and modify the `threshold` value in [`src/schedule.ts`](https://github.com/frejs/fre/blob/main/src/schedule.ts) directly, though this deviates from the standard library behavior.