When Network Throughput Hits a Wall
A financial services client called us last spring with a familiar complaint. Their Windows Server 2025 nodes were bleeding throughput under sustained traffic loads — CPU cores peaking unevenly, network performance inconsistent across the board. The infrastructure team had already checked the obvious: NIC drivers, MTU settings, VLAN configs. All clean.
The culprit was Get-NetAdapterRsc showing Receive Segment Coalescing disabled at the global offload level. One cmdlet fixed the immediate problem. But figuring out why it was disabled, and which adapters were affected across a multi-server environment, took a proper PowerShell audit. That audit process is what I want to walk through here.
What RSC Actually Does
Every time a packet arrives at your NIC, Windows has to process it. When you’re dealing with thousands of small TCP segments per second, that overhead accumulates fast. Receive Segment Coalescing addresses this directly: it parses incoming small packets and merges them into a single, larger packet before handing off to the TCP/IP stack.
Think of it like a mail room consolidating individual letters into batches before delivery. Same information, far fewer handoffs. The CPU cost of processing one large packet is significantly lower than processing fifty small ones — and at scale, that difference shows up as measurable CPU headroom.
RSC is distinct from RSS — Receive Side Scaling — which distributes receive traffic across multiple processor cores by hashing packet headers. You want both running. RSS spreads load; RSC reduces per-packet interrupt overhead. They complement each other. Treating them as either/or is a mistake I see in client environments more often than I’d like.
The Two-Layer Control Model
Here’s the nuance that trips people up: RSC has two independent layers of control. There’s a global TCP/IP offload setting that applies system-wide, and then there are per-adapter settings. You can have RSC enabled on the adapter and still see it silently fail if the global setting overrides it.
This was exactly the situation with our financial services client. The NIC hardware supported RSC. The adapter setting showed Enabled. But Get-NetOffloadGlobalSetting revealed ReceiveSegmentCoalescing as Disabled — left over from a migration project where someone toggled it off for testing and never went back.
Step 1: Audit Your Current State with Get-NetAdapterRsc
Before you change anything, audit what you have. Discovery first, changes second. That’s the rule across every engagement we run.
# Get RSC properties for a specific adapter
Get-NetAdapterRsc -Name "MyAdapter"
# Get all RSC-capable network adapters on the system
Get-NetAdapterRsc -Name "*"
# Filter to show only adapters with RSC actively enabled
Get-NetAdapterRsc -Name "*" | Where-Object -FilterScript { $_.Enabled }
That third command is what I reach for first in any new client environment. If the output is empty on a server with multiple NICs and high network utilization, that’s worth investigating immediately. You’re leaving performance on the table.
Reading the Output: What the Properties Mean
Get-NetAdapterRsc returns RSC state for both IPv4 and IPv6 separately. The properties that matter most in a diagnostic context are IPv4FailureReason and IPv6FailureReason. These tell you precisely why RSC isn’t working when it isn’t — no guessing required, no trial and error.
| Failure Reason | What It Means | Fix |
|---|---|---|
NoFailure |
RSC is working correctly | Nothing needed |
NicPropertyDisabled |
RSC disabled at adapter level | Enable-NetAdapterRsc |
NetOffloadGlobalDisabled |
Global RSC setting is off | Set-NetOffloadGlobalSetting |
WFPCompatibility |
Windows Filtering Platform conflict | Investigate WFP filters first |
NDISCompatibility |
NDIS driver issue | Update or replace driver |
ForwardingEnabled |
IP forwarding active on adapter | Expected — by design |
Capability |
Hardware doesn’t support RSC | Hardware limitation, stop here |
Unknown |
Driver-level issue | Check driver event logs |
When you see NetOffloadGlobalDisabled, that’s your signal to move to the global settings layer before touching anything at the adapter level.
Step 2: Check Global Offload Settings
Get-NetOffloadGlobalSetting gives you the system-wide TCP/IP offload picture. RSC, RSS, TCP Chimney, Task Offload, NetworkDirect — it’s all here in one cmdlet.
# Check global TCP/IP offload settings
Get-NetOffloadGlobalSetting
Look specifically at ReceiveSegmentCoalescing in the output. If that property reads Disabled while your adapters say Enabled, you’ve found your problem. The global setting overrides everything beneath it in the stack.
While you’re here, check PacketCoalescingFilter too. This controls whether the system coalesces packets that match Windows Filtering Platform filters. Default is Enabled on client SKUs, but behavior differs on Server editions. If you’re running deep packet inspection or any third-party firewall stack on the host, this can interact with RSC in ways that aren’t obvious until you’re chasing dropped packets at 2am.
Step 3: Enable RSC at the Right Layer
Once you know where the problem lives, fixing it is straightforward. Start at the global layer when that’s the root cause.
Fixing the Global Setting
# Enable RSC at the global TCP/IP offload level
Set-NetOffloadGlobalSetting -ReceiveSegmentCoalescing Enabled
Microsoft Learn has the full parameter reference for the NetOffloadGlobalSetting cmdlets if you want to dig into the other offload categories at the same time. This one flag, one command — immediate system-wide effect, no reboot required.
Enabling RSC Per-Adapter
If the global setting is fine but individual adapters still show RSC disabled, target them directly. The Microsoft documentation points you toward Set-NetOffloadGlobalSetting with -ReceiveSegmentCoalescing Enabled when the failure reason is NetOffloadGlobalDisabled, but adapter-level remediation uses different cmdlets.
# Enable RSC on a specific adapter
Enable-NetAdapterRsc -Name "MyAdapter"
# Enable RSC on all capable adapters in one pass
Enable-NetAdapterRsc -Name "*"
# Use Set-NetAdapterRsc for IPv4/IPv6 granularity
Set-NetAdapterRsc -Name "MyAdapter" -IPv4Enabled $true -IPv6Enabled $true
Fair warning: enabling RSC on a live adapter briefly restarts it. On a production server, that means a momentary link drop on that interface. Schedule this during a maintenance window. We’ve learned that lesson exactly once per client engagement, which is one time too many.
Building a Production-Ready RSC Audit Script
Running individual cmdlets is fine for a one-off investigation. For consistent management across multiple servers, you need something reusable, logged, and safe to hand off to whoever’s on call at 3am.
Version 1: Quick and Dirty (Ugly But Works)
# v1 - no frills, just the facts
Get-NetAdapterRsc -Name "*" | Select-Object Name, IPv4Enabled, IPv6Enabled, IPv4FailureReason, IPv6FailureReason
Get-NetOffloadGlobalSetting | Select-Object ReceiveSegmentCoalescing, PacketCoalescingFilter
Two lines. When you’re in the middle of an incident at 10pm, pretty isn’t the priority. Get the data, find the problem, fix it. Clean it up later.
Version 2: With Remediation Logic
# v2 - check and remediate, but no logging yet
$globalSettings = Get-NetOffloadGlobalSetting
if ($globalSettings.ReceiveSegmentCoalescing -eq 'Disabled') {
Write-Host "Global RSC disabled - enabling now." -ForegroundColor Yellow
Set-NetOffloadGlobalSetting -ReceiveSegmentCoalescing Enabled
Write-Host "Done." -ForegroundColor Green
}
$adapters = Get-NetAdapterRsc -Name "*"
foreach ($adapter in $adapters) {
if (-not $adapter.IPv4Enabled -or -not $adapter.IPv6Enabled) {
Write-Host "Enabling RSC on: $($adapter.Name)" -ForegroundColor Yellow
Enable-NetAdapterRsc -Name $adapter.Name
Write-Host "Enabled: $($adapter.Name)" -ForegroundColor Green
}
}
This handles the two-layer problem automatically. Checks global first, then sweeps adapters. Still missing logging and hardware capability checks — those come in v3.
Version 3: Production-Ready with Logging and Safety Checks
# v3 - production grade with logging, -AsJob support, hardware awareness
param(
[switch]$Remediate,
[string]$LogPath = "C:\Logs\RSC-Audit-$(Get-Date -Format 'yyyyMMdd-HHmm').log"
)
function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$entry = "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] [$Level] $Message"
Add-Content -Path $LogPath -Value $entry
Write-Host $entry
}
New-Item -ItemType Directory -Force -Path (Split-Path $LogPath) | Out-Null
Write-Log "RSC audit starting on $env:COMPUTERNAME"
# Check global offload layer first
$global = Get-NetOffloadGlobalSetting
Write-Log "Global ReceiveSegmentCoalescing: $($global.ReceiveSegmentCoalescing)"
if ($global.ReceiveSegmentCoalescing -eq 'Disabled') {
Write-Log "Global RSC is off." -Level "WARN"
if ($Remediate) {
Set-NetOffloadGlobalSetting -ReceiveSegmentCoalescing Enabled
Write-Log "Global RSC enabled via Set-NetOffloadGlobalSetting." -Level "FIX"
}
}
# Per-adapter audit and optional remediation
$adapters = Get-NetAdapterRsc -Name "*"
foreach ($adapter in $adapters) {
$status = "IPv4: $($adapter.IPv4Enabled) [$($adapter.IPv4FailureReason)] | IPv6: $($adapter.IPv6Enabled) [$($adapter.IPv6FailureReason)]"
Write-Log "Adapter: $($adapter.Name) | $status"
if ($Remediate -and (-not $adapter.IPv4Enabled -or -not $adapter.IPv6Enabled)) {
# Skip adapters that lack hardware RSC support - no point trying
$hwLimit = ($adapter.IPv4FailureReason -eq 'Capability' -or $adapter.IPv6FailureReason -eq 'Capability')
if (-not $hwLimit) {
# -AsJob queues adapter restart as background job - non-blocking across multiple adapters
Enable-NetAdapterRsc -Name $adapter.Name -AsJob | Out-Null
Write-Log "Queued RSC enable (background job) for: $($adapter.Name)" -Level "FIX"
} else {
Write-Log "Adapter $($adapter.Name) lacks RSC hardware support - skipping." -Level "WARN"
}
}
}
Write-Log "Audit complete. Log: $LogPath"
The -AsJob flag on Enable-NetAdapterRsc is the detail that earns its place in production. When you’re remediating multiple adapters, queuing each as a background job prevents the script from blocking on every adapter restart in sequence. We deploy this as a scheduled task across managed endpoints, with -Remediate only active during approved maintenance windows — run it without the flag for zero-risk ongoing audits.
RSS and RSC Together: Don’t Configure One Without the Other
While you’re already in the network offload settings, verify your RSS state. Get-NetAdapterRss shows which adapters have Receive Side Scaling enabled and how processor assignments are configured.
Get-NetAdapterRss -Name "*" | Select-Object Name, Enabled, NumberOfReceiveQueues, BaseProcessorNumber
A high-throughput data pipeline client we manage — running Windows Server 2025 across several file server nodes — saw measurable CPU headroom open up after enabling both RSS and RSC consistently. Same hardware, better throughput, lower CPU utilization under sustained load. That’s the combination working as intended.
If you’re managing backup traffic alongside production workloads, this matters more than most people expect. Properly tuned network adapters directly affect disaster recovery pipeline performance — particularly backup job completion windows where CPU saturation causes jobs to run long and miss their scheduled windows.
Where RSC Won’t Help (Be Honest About the Limits)
My opinion, and I’ll stand behind it: enabling RSC everywhere without checking the environment first is sloppy engineering. There are specific scenarios where RSC is actively disabled by design, and fighting that is a waste of time.
IP Forwarding Environments
If an adapter is routing traffic between subnets — IP forwarding enabled — Windows disables RSC on that adapter automatically. The ForwardingEnabled failure reason is telling you it’s working correctly. Coalescing segments across routing boundaries breaks things downstream, and the OS knows this. Don’t try to work around it.
WFP and Third-Party Driver Conflicts
We got called in after a manufacturing client’s previous MSP had enabled RSC globally without checking what was running in the filter chain. A legacy NDIS filter driver from their DPI appliance wasn’t handling coalesced frames correctly. The result was sporadic packet drops, difficult to reproduce, that took two days to trace to root cause. If you see WFPCompatibility or NDISCompatibility as failure reasons, investigate the filter stack before touching anything. SANS has solid material on network stack filter driver interactions for those who want to go deeper on the WFP compatibility angle.
Virtual NICs in Hypervisor Environments
In Hyper-V or VMware environments, RSC availability depends on the virtual NIC type and the host driver stack. VMware’s documentation on network offloads in vSphere covers this in detail — not all virtual adapters expose RSC capability to the guest OS. When Get-NetAdapterRsc shows Capability as the failure reason, that’s a hardware or virtual hardware limitation. No amount of PowerShell changes that reality.
Where This Fits in Your Broader Windows Server Practice
RSC sits alongside a family of network offload settings that most admins configure once during initial build and never revisit. That’s a missed opportunity for consistent, documented performance baselines.
If you’re building a Windows Server configuration baseline, network offload settings belong in your standard checklist alongside NIC teaming, interrupt moderation, and power plan configuration. They’re not security controls, but they directly affect the performance envelope of every service running on that box — including security tooling that processes network traffic at the host level.
The same applies when you’re optimizing infrastructure supporting CI/CD pipelines that push large build artifacts over the network. The receiving end matters as much as the pipeline configuration itself. Tuning the NIC stack is low-effort, high-return work that compounds across every workload running on the server.
Run It, Log It, Baseline It
RSC configuration follows a clear three-step workflow: audit with Get-NetAdapterRsc, check the global layer with Get-NetOffloadGlobalSetting, and remediate with Set-NetOffloadGlobalSetting and Enable-NetAdapterRsc. The failure reason properties do the diagnostic work for you — read them before touching anything.
The v3 script above is production-ready as written. Run it without -Remediate for a safe, logged audit on any server at any time. Add -Remediate during a maintenance window to fix what it finds. Keep the logs — you’ll want a documented baseline when someone asks why performance changed after that migration six months from now.
If you want SSE to run this audit across your Windows Server estate — or fold it into a broader network configuration and performance baseline — reach out to us here.


