-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
Extend Blazor's circuit pause/resume feature to opt-in to automatically pause circuits when we detect the user is not active. We do this when the browser tab is hidden for a configurable period (default: 2 minutes) and optionally pausing circuits on visible tabs when user inactivity is detected through browser events.
Motivation and goals
Current behavior: When users switch away from a Blazor Server app, the circuit remains active indefinitely as long as the SignalR connection stays alive. On desktop browsers, WebSocket connections can remain stable for hours or even days in hidden tabs, meaning circuits continue consuming server resources (CPU, memory) even though the user is not actively using the app. While .NET 10.0 automatically persists circuit state on ungraceful disconnect, this only occurs when the connection is actually lost—which may never happen for hidden tabs with stable network conditions.
This feature addresses the following needs:
- Desktop browsers can keep hidden tab circuits alive indefinitely (hours or days), wasting server resources until the user closes the tab or network fails
- High-traffic applications accumulate many idle circuits as users switch between tabs, limiting scalability and increasing hosting costs for cloud-hosted apps
- Developers currently must write custom JavaScript to implement proactive pausing, reinventing a common pattern seen in Gmail, Slack, and other web apps
- .NET 10.0's circuit state persistence infrastructure and existing
Blazor.pause()/Blazor.resume()APIs make automatic pausing practical, but require manual implementation - A built-in, configurable solution would provide consistent behavior and developer convenience while freeing server resources in ~2 minutes instead of waiting indefinitely while the connection remains alive.
In scope
- Automatic pause/resume for hidden tabs with configurable delay (default: 2 minutes), automatic resume on visibility, and graceful handling of race conditions when users return during pause operations
- Simple opt-in configuration API with diagnostics/logging for monitoring pause/resume events
Secondary (extension):
- Visible tab inactivity detection with configurable timeout (default: 5 minutes) and customizable activity events (mousedown, keydown, touchstart, wheel, scroll)
Out of scope
- Extensibility/customization: No server-side detection, user warnings, custom pause/resume hooks, or component-level opt-out (app-level only)
- Granular control: No per-user configuration, cross-tab coordination, or pause prevention for specific components
Risks / unknowns
// TBD
Examples
Example 1: Basic opt-in (default 2-minute timeout)
wwwroot/app.js:
// Enable automatic pause after 2 minutes of tab being hidden
Blazor.start({
circuit: {
autoPause: {
enabled: true,
}
}
});Developer experience:
- User opens Blazor app, uses it normally
- User switches to another tab (email, documentation, etc.)
- After 2 minutes, circuit automatically pauses
- Server resources freed, state saved to client storage
- User returns 10 minutes later
- Circuit automatically resumes, state restored
- User continues exactly where they left off
Example 2: Custom timeout configuration
wwwroot/app.js:
// Aggressive resource management with 30-second delay
Blazor.start({
circuit: {
autoPause: {
enabled: true,
hiddenDelay: 30000 // 30 seconds - aggressive
}
}
});Developer experience:
- High-traffic app wants aggressive resource management
- Sets 30-second delay for hidden tabs
- Users who quickly switch back (< 30s) don't experience pause/resume
- Users who stay away longer have circuit paused faster
Example 3: Secondary feature - Visible tab inactivity detection
wwwroot/app.js:
// Enable both hidden tab and visible inactivity detection
Blazor.start({
circuit: {
autoPause: {
enabled: true,
hiddenDelay: 120000, // 2 minutes for hidden tabs
// Optional: Also pause on visible inactivity
inactivity: {
enabled: true,
timeout: 300000, // 5 minutes of no user interaction
events: ['mousedown', 'keydown', 'touchstart', 'wheel', 'scroll']
}
}
}
});Developer experience:
- User opens dashboard, reads data
- User steps away without closing tab (gets coffee, meeting, etc.)
- No interaction for 5 minutes
- Circuit automatically pauses
- User returns, moves mouse
- Circuit resumes automatically
- Dashboard updates with latest data