WinCC OPC Server Slow Write: Resolving Bulk Tag Transfer Delays

David Krause15 min read
OPC / OPC UASiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Statement: WinCC OPC DA Write Latency Drift

A WinCC runtime is configured as an OPC Data Access server for a customer MES system. The MES writes roughly 500 tags per cycle to the WinCC tag database; those tags are bound to approximately 5000 Modbus TCP field devices downstream. At commissioning, a 500-tag bulk write completes in about 10 seconds. After several weeks of continuous operation, the same bulk write takes about 30 seconds, even though no engineering, firmware, network, or device change has occurred.

The symptom is reproducible, slow, and silently degrades. The OPC server stays online, the Modbus TCP channel stays connected, and the network is healthy. The performance loss is therefore a software-side issue: most often in the OPC client polling model, with secondary contributors in WinCC channel update times and the WinCC OPC server's internal transaction handling.

Field signature: latency grows monotonically over days, not minutes. Hardware faults (link loss, port flap) fail loudly. Software-side issues grow quietly until they cross a threshold where operators notice.

Symptom Snapshot

Parameter At Commissioning After Several Weeks Notes
Bulk write size 500 tags 500 tags Unchanged
Write round-trip time ~10 s ~30 s 3x degradation
WinCC tag count 5000 5000 Unchanged
Modbus TCP devices Per topology Per topology Unchanged
Network 100 Mbit/s Ethernet 100 Mbit/s Ethernet Unchanged
WinCC / MES software Baseline Unchanged No rebuilds

WinCC OPC DA Server Architecture

WinCC includes a built-in OPC Data Access server. The server is registered as a COM out-of-process server and exposes all WinCC internal tags, regardless of which physical channel those tags are bound to. For projects using Modbus TCP field devices, those tags are first acquired by the WinCC Modbus TCP channel (or, in some configurations, by a SIMATIC NET OPC server in front of WinCC) and then re-exposed through the WinCC OPC DA server interface.

Per the TIA Portal documentation for OPC in WinCC panels and WinCC Runtime Advanced, an HMI device operating as an OPC server can serve multiple OPC clients, and an HMI device operating as an OPC client can connect to a maximum of eight OPC servers simultaneously. WinCC Professional and WinCC v7 runtimes can accept many more concurrent client connections but are still subject to the same item-throughput ceilings that govern any OPC DA 3.0 server.

Using OPC in WinCC (Panels, Comfort Panels, RT Advanced) - TIA Portal V20 documentation

Component Roles

  • WinCC tag database: in-memory store of all 5000 tags. Each tag has an acquisition cycle, a limit, and a current value.
  • Modbus TCP channel: the WinCC driver that polls the field devices and refreshes tag values. Cycle time is configurable per connection or per tag group.
  • WinCC OPC DA server: COM server that maps WinCC tag names to OPC item IDs and serves them to any connected OPC client.
  • MES OPC client: external application that connects to the WinCC OPC server, browses the tag tree, and issues Read / Write calls.

Performance problems with bulk writes almost always come from the last two layers: the OPC client polling logic and the OPC server's handling of synchronous Write requests. The Modbus TCP channel rarely causes write latency in the MES-to-WinCC direction because the bottleneck is upstream of the channel.

Why Latency Grows After Commissioning: Root Cause Analysis

Three factors combine to produce the slow degradation that operators see in the field.

1. Synchronous Polling from the OPC Client

An OPC DA client that does not subscribe to a group and does not use _DataChange callbacks is forced to drive its own read/write loop. In a VB or VBA application, the typical pattern is a tight SyncWrite loop on the main thread:

OPCMygroup.IsSubscribed = False
Dim ClientHandles(1 To 500) As Long
Dim Values(1 To 500) As Variant
' ... populate ClientHandles and Values ...
OPCMygroup.SyncWrite 500, ClientHandles, Values, Errors
' UI thread blocked here for the full transaction

Each call to SyncWrite is synchronous; the calling thread blocks until the WinCC OPC server completes the transaction. If the MES executes this loop on its main thread, the MES UI thread is blocked for the full 10 to 30 seconds during every bulk write. The OPC server, in turn, must serialize each Write call, allocate COM memory for the variant array, copy the values into the WinCC tag database, and notify any subscribed clients of the change.

This pattern does not break at commissioning. The MES, WinCC, and the OS are warm; the COM apartments are initialized; the network stack is hot. After a few weeks, however, additional subscribed clients, fragmentation of the variant arrays, and the natural memory growth of long-running COM servers push the same synchronous loop over a tipping point where transaction overhead dominates the actual data transfer time.

2. No Event-Triggered Updates

The cleanest cure is to never poll at all. The OPC DA spec allows the client to subscribe to a group and receive callbacks only when values change. This is the _DataChange event, with the standard signature:

Private Sub OPCMygroup_DataChange( _
    ByVal TransactionID As Long, _
    ByVal NumItems As Long, _
    ClientHandles() As Long, _
    ItemValues() As Variant, _
    Qualities() As Long, _
    TimeStamps() As Date)
    ' React only when the server has new data
End Sub

When the client subscribes, the OPC server is responsible for sampling values at the requested update rate and pushing only changed values to the client. The client never has to ask. The MES developer can use IsSubscribed = True to opt into this model and implement _DataChange to react only when the server has new data.

3. No Dead Band

Dead band is the percentage change required before the server reports a new value to a subscribed client. A dead band of 1.0% means a tag must change by at least 1% of its engineering range before the server fires _DataChange. This single setting, applied across all subscribed tags, can reduce the OPC traffic between WinCC and the MES by 80% to 95% on process values that drift slowly.

Bulk writes from the MES to WinCC are not the same as subscribed reads, so dead band does not directly affect write latency. However, when the MES also subscribes to read back the values it just wrote, dead band prevents the read-back stream from drowning the write queue. Always configure dead band on every subscribed group, not just the write-only groups.

OPC Group Subscription Model in Detail

An OPC DA group is a collection of items (tags) that the client reads or writes as a unit. Each group has its own update rate, dead band, language, and active state. There are two operating modes for a group:

Mode OPC Property Direction of Data Flow When to Use
Polled IsSubscribed = False Client pulls Rare reads where the client wants explicit control of timing
Subscribed IsSubscribed = True Server pushes on _DataChange Continuous reads; bulk writes; any high-frequency path

For a 500-tag bulk write that takes 30 seconds, switching the MES group from polled to subscribed and using AsyncWrite instead of SyncWrite is the single highest-impact change. AsyncWrite returns immediately, freeing the MES thread, and the server processes the writes on its own thread pool. The MES can then use the AsyncWriteComplete event to know when the transaction is finished.

Reference OPC DA Automation Code

' Create the OPC Server object (WinCC runtime)
Set objServer = CreateObject("OPC.SimaticHMI.HmiRTm.1")

' Add a group with 1-second update rate and 1.0% dead band
Set objGroup = objServer.OPCGroups.Add("MES_BulkGroup")
objGroup.IsSubscribed = True
objGroup.DeadBand = 1.0
objGroup.UpdateRate = 1000

' Add 500 items to the group (ClientHandles pre-populated)
objGroup.OPCItems.AddItems 500, ItemIDs, ClientHandles

' Issue an asynchronous write - returns immediately
Dim txnID As Long
Dim errCodes() As Long
objGroup.AsyncWrite 500, ClientHandles, Values, _
    TransactionID := txnID, _
    ErrorCodes := errCodes

' Handle the completion event elsewhere
Private Sub objGroup_AsyncWriteComplete( _
    ByVal TransactionID As Long, _
    ByVal NumItems As Long, _
    ClientHandles() As Long, _
    Values() As Variant, _
    Qualities() As Long, _
    TimeStamps() As Date)
    ' Transaction finished; safe to issue the next bulk write
End Sub

This pattern is documented in the OPC DA Automation 2.0 specification. The WinCC OPC server implements AsyncWrite and AsyncWriteComplete as required by the spec.

Modbus TCP Channel Configuration in WinCC

For the field side, the Modbus TCP channel in WinCC v7 (channel type "Modbus TCPIP") and the Modbus TCP driver in WinCC Professional / TIA Portal acquire tag values from the field devices. Three parameters dominate the write path from the OPC server back to the Modbus devices:

Parameter Location in WinCC Effect on Bulk Write Latency
Update time Channel / connection / tag Lower = more CPU per scan. Set to the slowest acceptable value for the process.
Connection pool size Channel unit configuration WinCC opens multiple TCP sockets; more sockets = more parallel polls but more load.
Timeout / retries Channel unit configuration A flaky device with retries can block the channel queue and starve OPC write-back.

The MES bulk write does not directly touch the Modbus TCP channel. The OPC server writes the values into the WinCC tag database, and the Modbus TCP channel reads from the same database and forwards the values to the field. If the field writeback queue is the bottleneck, the symptom shows as OPC write timeouts from the MES, not as slow completion of the OPC write itself. Diagnose which side is slow before tuning.

Diagnostic Procedure

Follow this sequence. Do not skip steps; the order is important because each step rules out a layer.

Step 1: Capture Baseline

Run a controlled bulk write from the MES and time the round trip. Use a known payload (500 tags, fixed values) and a fixed schedule. Record the latency every hour for 24 hours. Plot it. Monotonic growth confirms a software-side issue; flat high latency points at a network or Modbus problem.

Step 2: Check WinCC OPC Server Log Files

WinCC writes OPC-related diagnostic information under the diagnose folder. The path is:

C:\Program Files\Siemens\WinCC\diagnose

Look for OPC*.log files and for entries that contain "Write" or "AsyncWrite". Long-running sessions accumulate large log files; a log that has stopped growing is normal, a log that grows faster than the workload indicates an internal loop. Capture the most recent 1000 lines and correlate timestamps with the MES write events.

Step 3: Wireshark Capture on the OPC Traffic

OPC DA uses DCOM, which by default negotiates dynamic TCP ports from RPC (typically starting at port 135 for the endpoint mapper). Capture with the following display filter on both the MES station and the WinCC station:

tcp.port == 135 || dcerpc || opcda

Save a 60-second capture that includes at least one full 500-tag bulk write. Then verify:

  • The MES is opening one group, not 500 separate connections.
  • The MES is sending one Write per group, not one per tag.
  • The WinCC server's response latency per Write is consistent; outliers indicate a blocked COM apartment.

If the Wireshark capture shows hundreds of individual IOPCItemIO::Write calls instead of a single group SyncWrite or AsyncWrite, the MES application is bypassing the OPC group model. That is a client-side bug, not a WinCC problem.

Step 4: Performance Monitor (perfmon) on the WinCC Station

Open perfmon.msc on the WinCC station and add the following counters during a controlled bulk write:

Counter Object Counter What it Tells You
Process % Processor Time for the OPC server process CPU saturation
Process Private Bytes for the OPC server process Memory leak indicator
Process Handle Count for the OPC server process Handle leak indicator
.NET CLR Memory # Bytes in all Heaps (if the MES is .NET) GC pressure
TCPv4 Connections Established Socket churn on the MES side

If private bytes grow monotonically across a controlled test where bulk write counts are constant, the OPC server is leaking. Apply the WinCC service packs for the installed version. If the leak is on the MES, escalate to the MES vendor; you cannot fix their memory leak from the WinCC side.

Step 5: Check the MES OPC Client Implementation

Ask the MES team to confirm three properties of their OPC client configuration:

  1. Group subscription state: IsSubscribed = True for the bulk write group.
  2. Write mode: AsyncWrite is used, not SyncWrite.
  3. Dead band: configured at 0.5% to 1.0% for analog tags, 0 for digital tags.

If the MES code is frozen and cannot be modified, the only remaining levers are on the WinCC side: tag-side update times, channel configuration, and splitting the bulk write into multiple smaller groups.

Tuning the WinCC OPC Server Side

When the MES code is frozen, you must work with the WinCC configuration to reduce write latency. The following knobs are available without changing the MES application.

Reduce Update Time on the WinCC Tag Database

WinCC tags have an update time. For tags written by the MES, set the update time to "On Change" or to the slowest acceptable cycle. This prevents the tag manager from re-reading the value at high frequency when the MES has just written it.

Split the 5000-Tag Database into Functional Groups

WinCC internal structure benefits from grouping tags by function block or by acquisition channel. Tags in the same group share a scheduling slot, which improves cache locality and reduces the per-write overhead. A flat 5000-tag database with no grouping pays a small per-tag overhead that adds up on a 500-tag bulk write.

Verify the Modbus TCP Channel Is Not the Bottleneck

Open WinCC Channel Diagnosis and confirm the write-back queue length for each Modbus TCP connection. If the queue is constantly greater than 0, the field side cannot keep up, and the OPC write latency will reflect that. Increase the connection pool size, reduce the per-connection update time, or split the field devices across multiple Modbus TCP channels.

Limit OPC Client Connections on the WinCC Side

If multiple OPC clients connect to the same WinCC server, each subscription consumes internal slots. Audit the OPC client sessions and disconnect unused clients. The DCOM session list in dcomcnfg on the WinCC station shows all active OPC clients; close the ones that are not in production use.

Verification: Confirming the Fix

After applying the client-side subscription change or the server-side tuning, run a 24-hour soak test with the same 500-tag bulk write every 60 seconds. Plot the round-trip latency. The expected results:

Configuration Round-Trip Latency (500 tags) Memory Growth on WinCC
Polled MES, SyncWrite, no dead band (baseline) 10 s to 30 s, growing Steady growth
Subscribed MES, AsyncWrite, 1% dead band 0.5 s to 1.5 s, stable Flat after warmup
Frozen MES, server-side tag grouping, slow update times 5 s to 10 s, stable Flat after warmup

A flat latency profile over 24 hours is the success criterion. If the latency is low but still drifts, a leak is still present and the MES code must be inspected, not the WinCC configuration.

Performance Tuning Matrix

Use this matrix as a triage guide when latency drifts back into the unacceptable range.

Symptom First Check First Fix
Round-trip grows over hours MES group subscription state Set IsSubscribed = True, switch to AsyncWrite
Round-trip grows over days OPC server process private bytes Apply WinCC updates, restart runtime weekly
Round-trip is consistently high Wireshark capture on DCOM Collapse N individual writes into one group SyncWrite / AsyncWrite
Round-trip is bursty WinCC diagnose log timestamps Increase update rate, reduce Modbus TCP connection count
MES UI freezes during write MES source code Move SyncWrite to a worker thread

When the Modbus TCP Channel Must Change

If the MES bulk write is mostly writes to tags whose values must be pushed to the field, the Modbus TCP channel's write-back path is the actual bottleneck, not the OPC server. In that case, the cure is to bypass the WinCC OPC server for the bulk write path and use SIMATIC NET as a Modbus TCP gateway. SIMATIC NET supports the Modbus TCP protocol as an OPC server, and the MES can connect directly to the SIMATIC NET OPC server instead of routing through WinCC.

To verify that the SIMATIC NET path is correct for the project, confirm the following:

  1. The MES requires a subset of the 5000 tags, not the full database.
  2. The MES-to-field latency must be in the sub-second range.
  3. WinCC is no longer required to display the MES-driven values.

If all three are true, replacing the WinCC OPC server in the MES write path with a SIMATIC NET OPC server is the right move. Otherwise, the WinCC OPC server is doing useful work (logging, alarming, display) and must stay in the path.

Key Takeaways

  • Slow drift in OPC write latency is almost always a client-side polling issue, not a WinCC or network issue.
  • Use IsSubscribed = True and AsyncWrite on the MES side. SyncWrite blocks the MES thread and serializes the server.
  • Configure dead band at 0.5% to 1.0% on every subscribed group to cut read-back traffic by an order of magnitude.
  • WinCC's diagnose folder and a Wireshark capture on DCOM are the two diagnostic sources that actually tell you what is happening.
  • When the MES code is frozen, server-side tuning (tag grouping, slower update times, splitting the database) is the only path left. The cure is partial.

How many OPC tags can a WinCC runtime handle concurrently?

WinCC v7 and WinCC Professional runtimes do not publish a hard item count. The practical limit is governed by update time, dead band, and the host CPU. With 1-second updates and 1% dead band, a 5000-tag database is comfortable on a quad-core industrial PC. The OPC throughput ceiling is reached long before the item count ceiling.

Why does my bulk write time grow from 10 s to 30 s with no changes?

The most common cause is a synchronous write loop in the OPC client. The MES issues SyncWrite on 500 tags from its main thread, which blocks the thread and serializes the server. Memory growth in long-running COM servers, fragmentation of the variant array, and accumulated queue depth push the same loop over a tipping point. Switch the MES group to IsSubscribed = True and use AsyncWrite.

What is the practical difference between SyncWrite and AsyncWrite in OPC DA?

SyncWrite blocks the calling thread until the server confirms every write. AsyncWrite returns immediately and signals completion through the AsyncWriteComplete event. For a 500-tag bulk write, AsyncWrite is mandatory; SyncWrite will serialize the MES UI thread for the full transaction.

Where are the WinCC OPC server log files located?

The default location is C:\Program Files\Siemens\WinCC\diagnose. Look for OPC*.log files. Timestamps in the log can be correlated with MES write events to confirm whether the server itself is the bottleneck or whether it is waiting on the client.

Can I bypass the WinCC OPC server and talk directly to the Modbus TCP devices?

Yes, using SIMATIC NET as a Modbus TCP gateway. The MES connects to the SIMATIC NET OPC server, and the field devices are reached directly. This is the right architecture when WinCC no longer needs to display the MES-driven values; otherwise the WinCC OPC server still has work to do and must stay in the path.

Back to blog