Windows Event Forwarding at scale
Windows Event Forwarding that holds up: collectors, source-initiated subscriptions, XPath queries, delivery tuning, Security log access and health checks.
The audit policy and Sysmon baseline ends with four lines on forwarding: run wecutil qc, create a subscription, point sources at the collector, grant log access. That's enough for a lab. In production, WEF fails in quieter ways: a subscription that pulls ten times more than planned, a collector that falls behind, domain controllers that never forward their Security log. This guide covers design, configuration and operation of Windows Event Forwarding for thousands of hosts.
Architecture in one paragraph
Sources (every Windows host) run an event log forwarding client that uses the WinRM service. Collectors run the Windows Event Collector service (Wecsvc) and hold subscriptions: XPath queries plus delivery settings. With source-initiated subscriptions, sources learn the collector address from Group Policy, pick up the subscriptions meant for them, and push matching events over WinRM. Collected events land in ForwardedEvents (or a custom log), where a SIEM agent picks them up. Source-initiated is the right model at scale; collector-initiated subscriptions need every source listed individually.
Step 1: design the subscriptions
Group events by purpose, not by log. A typical set:
| Subscription | Targets | Content |
|---|---|---|
| Baseline-Security | All computers | Logons, account changes, process creation, service and task creation, log clearing |
| DC-Security | Domain controllers | Kerberos, directory changes, replication rights, group changes |
| PowerShell | All computers | 4103, 4104, 400 |
| Sysmon | Hosts running Sysmon | Sysmon Operational, already tuned at the source |
| Defender | All computers | 1116, 1117, 5001, 5007 |
Small, focused subscriptions are easier to troubleshoot and size, and a broken query only breaks one of them. Use the security event ID reference to decide what goes into each.
ForwardedEvents or custom logs
By default every subscription writes to ForwardedEvents, one log for everything. That's simple, but a noisy subscription can push out important events, and the SIEM agent has to read one very large log. The alternative is custom event channels: a small manifest DLL registered on the collector that creates separate logs, for example one for Security, one for Sysmon and one for PowerShell, each with its own size. Community projects publish ready-made WEF channel manifests and subscription sets you can adapt. Custom channels add a build and deployment step, so start with ForwardedEvents and move once volume or retention needs demand it.
Step 2: build the collector
Use dedicated collectors (not domain controllers), sized for disk I/O first. On each collector:
wecutil qc /q # configure Wecsvc (delayed automatic start)
wevtutil sl ForwardedEvents /ms:4294967296 # 4 GB bufferAllow inbound TCP 5985 from source subnets in the host firewall. The collector is a high-value log host; manage it from your admin tier and apply WinRM hardening to it like any other server.
At larger scale, consider giving the collector service its own process with sc.exe config Wecsvc type= own, so it doesn't share a service host with WinRM. Microsoft documents related changes to HTTP URL reservations for that setup; follow the current collector scalability guidance rather than copying snippets from forums.
Step 3: write the subscription XML
Create subscriptions from files so they live in source control. A source-initiated subscription for domain computers:
<Subscription xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription">
<SubscriptionId>Baseline-Security</SubscriptionId>
<SubscriptionType>SourceInitiated</SubscriptionType>
<Description>Core security events from all domain computers</Description>
<Enabled>true</Enabled>
<Uri>http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog</Uri>
<ConfigurationMode>Custom</ConfigurationMode>
<Delivery Mode="Push">
<Batching>
<MaxItems>50</MaxItems>
<MaxLatencyTime>60000</MaxLatencyTime>
</Batching>
<PushSettings>
<Heartbeat Interval="3600000"/>
</PushSettings>
</Delivery>
<Query><![CDATA[
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[(EventID=4624 or EventID=4625 or EventID=4648 or EventID=4672)]]</Select>
<Select Path="Security">*[System[(EventID=4688 or EventID=4697 or EventID=4698 or EventID=4720 or EventID=4732)]]</Select>
<Select Path="Security">*[System[(EventID=1102)]]</Select>
<Select Path="System">*[System[(EventID=7045 or EventID=104)]]</Select>
</Query>
</QueryList>
]]></Query>
<ReadExistingEvents>false</ReadExistingEvents>
<TransportName>HTTP</TransportName>
<ContentFormat>RenderedText</ContentFormat>
<Locale Language="en-US"/>
<LogFile>ForwardedEvents</LogFile>
<AllowedSourceNonDomainComputers></AllowedSourceNonDomainComputers>
<AllowedSourceDomainComputers>O:NSG:BAD:P(A;;GA;;;DC)S:</AllowedSourceDomainComputers>
</Subscription>wecutil cs .\Baseline-Security.xml
wecutil gs Baseline-Security # show the subscription as the collector sees itKey choices in that file:
- AllowedSourceDomainComputers is an SDDL string.
DCis Domain Computers. For the DC-Security subscription, grant the domain controllers group instead, or a dedicated AD group's SID, so each subscription only reaches the hosts meant for it. - ReadExistingEvents
falsemeans sources forward only new events. Setting it totrueon a new subscription makes every source upload its entire matching history at once, which can flatten a collector. - ContentFormat
RenderedTextincludes the rendered message, which many SIEM parsers expect;Eventsis smaller because it sends raw XML only. - Delivery. Custom mode with a 60-second
MaxLatencyTimeis a good default for security events. The built-in modes are Normal (batched, up to 15 minutes), MinLatency (about 30 seconds) and MinBandwidth (hours, for slow links). - Query size. Very long XPath expressions can fail to apply. Split IDs across several
Selectelements as shown, rather than one hugeorchain.
Step 4: configure the sources by GPO
On the sources, under Computer Configuration > Policies > Administrative Templates > Windows Components > Event Forwarding:
- Configure target Subscription Manager = Enabled, with
Server=http://wec01.corp.example:5985/wsman/SubscriptionManager/WEC,Refresh=60. Use the collector's FQDN so Kerberos works. You can list more than one server; each source then forwards to every listed collector, which gives redundancy but doubles volume.
Then make sure sources can actually read and send the logs:
- WinRM service running. The forwarding client needs it, even on workstations without a WinRM listener. Set Windows Remote Management (WS-Management) to Automatic under Security Settings > System Services if your baseline disables it.
- Security log access. The forwarder runs as Network Service, which can't read the Security log by default. Either add
NT AUTHORITY\NETWORK SERVICEto the local Event Log Readers group through Group Policy, or append(A;;0x1;;;NS)to the Security channel's access string with Windows Components > Event Log Service > Security > Configure log access. Domain controllers have no local groups, so use the log-access method or the domain's builtin Event Log Readers group there.
Split sources across collectors by GPO scope, for example one GPO per OU or site pointing to a different collector. WEF has no built-in load balancer.
What breaks
- Security events from DCs missing is almost always the log-access step. Check the channel access string with
wevtutil gl Security. - Wrong collector name (short name or IP) means no Kerberos, so sources can't authenticate.
- Subscription runtime state in the registry grows with every source; very large single subscriptions make the collector slow to start. More, smaller subscriptions and more collectors fix this.
- Collector disk fills if the SIEM agent stops reading. ForwardedEvents is a buffer, not an archive.
- Firewall changes on collectors or a disabled WinRM service on sources stop forwarding silently.
Step 5: size and monitor
Size on events per second, measured, not on host count. Pilot each subscription on a representative group, then read the rate on the collector and in your SIEM. Keep enough headroom that the collector can absorb catch-up bursts after an outage, when every source sends its backlog.
Check subscription health from the collector:
wecutil gr Baseline-Security # runtime status: each source, state, last heartbeatSources in an inactive state, or with a last heartbeat older than the heartbeat interval, need attention. On a source, errors appear in Applications and Services Logs > Microsoft > Windows > Eventlog-ForwardingPlugin > Operational, and connectivity can be tested with Test-WSMan wec01.corp.example.
Build three alerts in the SIEM: a collector that stops sending, a subscription whose source count drops sharply, and critical hosts (domain controllers, Tier 0 servers) that haven't forwarded any event in the last hour.
Step 6: get events into the SIEM
Run your SIEM's agent on the collectors only. For Microsoft Sentinel, the Azure Monitor Agent can collect ForwardedEvents through the Windows Forwarded Events data connector. For other SIEMs, point their Windows agent at the ForwardedEvents log (or your custom logs). Firewall rule logging from firewall logging and monitoring and Sysmon from Sysmon deployment and tuning can travel through the same pipeline.
Verify it
- On a source:
gpresult /r /scope computershows the Event Forwarding GPO;wevtutil gl Securityshows Network Service access. - Generate a known event, for example a failed logon with a wrong password (4625).
- On the collector:
Get-WinEvent -LogName ForwardedEvents -MaxEvents 20shows it within the configured latency. - In the SIEM: the event is searchable with the right host name and timestamp.
wecutil grlists the expected number of active sources.
More on the whole logging stack on the audit and logging topic page.
Checklist
- Subscriptions designed by purpose and stored as XML in source control
- Dedicated, hardened collectors with ForwardedEvents sized as a buffer
- Source-initiated subscriptions scoped with AllowedSourceDomainComputers
- ReadExistingEvents false on new subscriptions; custom delivery latency set
- Target Subscription Manager GPO uses the collector FQDN
- WinRM service running on sources; Security log readable by Network Service, including on DCs
- Collector load measured in events per second, with headroom for backlogs
- Subscription health, source counts and silent critical hosts alerted
Frequently asked questions
Is Windows Event Forwarding traffic encrypted?
Yes. In a domain, source-initiated forwarding over HTTP on port 5985 authenticates with Kerberos and encrypts the payload with the session key, just like other WinRM traffic. For sources outside the domain, use HTTPS with client and server certificates. Keep 'Allow unencrypted traffic' disabled on sources and collectors so the protection cannot be switched off.
How many sources can one collector handle?
It depends on event rate far more than on host count. A collector receiving only a few focused event IDs from workstations handles many thousands of sources, while one receiving full Security logs from domain controllers handles far fewer. Microsoft's rule of thumb for a stable collector on commodity hardware is about 3,000 events per second on average across all its subscriptions. Measure events per second in a pilot and leave headroom below that figure.
Do I still need WEF if I have a SIEM agent?
Not necessarily. If an agent already collects the same events from every host with low latency, WEF adds little. WEF is valuable where you can't or don't want to deploy agents everywhere: it is built into Windows, needs no licence, and lets a few collector servers carry the SIEM agent instead of every endpoint.
Windows Event Forwarding at scale