What's New in OPC UA .NET Standard 2.0
August 9, 2026 · View on GitHub
This document is a developer-facing tour of the changes between 1.5.378 and 2.0. It is organised by theme and layer; each section describes the broad-stroke change with a paragraph and links to the deeper feature documentation in this folder.
If you are migrating an existing application, the companion Migration Guide is the prescriptive, API-level reference.
At a glance
- The OPC UA built-in types are now allocation-friendly value types, with
a
Variant-first public API, a newByteStringtype, andArrayOf<T>/MatrixOf<T>replacing untyped array shapes. - Server- and client-side stacks are now fully
async/awaitwith cancellation flowing through the request lifetime,TimeProvidereverywhere, and the newAsyncCustomNodeManagerpowering all built-in NodeManagers. - A first-class hosting story:
services.AddOpcUa()andIOpcUaBuilderplug servers and clients intoMicrosoft.Extensions.DependencyInjectionand the .NET Generic Host, complemented by a fluent server andManagedSessionfluent client builder. - Native AOT support across the stack, including AOT-clean source generators, NodeSet export/import, and reference servers/clients.
- New companion-spec coverage: Part 9 (Alarms & Conditions), Part 11 (Historical Access) + Part 13 (Aggregates), Part 16 (State Machines), Part 17 (Alias Names), Part 18 (Role Management), Part 20 (File Transfer), Part 100 (Device Integration), plus OPC 10100-1 WoT Connectivity and a Local Discovery Server.
- Source generators emit NodeManagers, typed
ObjectTypeproxies, andIEncodeabledata types from model design XML, removing hand-written boilerplate while staying AOT-clean. - GDS is now Part 12 full-compliance, with arbitrary certificate groups, custom group support, and modernised Push/Pull APIs.
- OPC UA Part 4 §6.6 redundancy plus opt-in distributed high availability.
Server and client redundancy (
Server.ServerRedundancy/ServiceLevel,ManagedSession.WithServerRedundancy()) ship in the box, and newOpc.Ua.Redundancy(.Server/.Client/.Kubernetes)packages add distributed address-space / session / subscription mirroring over an in-package CRDT (eventual) or Raft (strong) shared store, with a Kubernetes deployment guide. - An MCP server ships in the box so an LLM/Copilot can drive an OPC UA client; and a 2.0 Migration Analyzer + code fixer automates the mechanical parts of upgrading to v2.
Breaking changes at a glance
2.0 is the first major break of the public API since the project moved to
.NET Standard. The biggest sources of breakage are the readonly-struct
built-ins (NodeId, ExtensionObject, Variant, DataValue,
QualifiedName, LocalizedText, ArrayOf<T>), the Variant-for-object
pivot in code and API, the new IEncodeableFactoryBuilder and IType
hierarchy, the removal of Newtonsoft.Json from Opc.Ua.Core, the
ManagedSession family next to the classic Session, and the move to
AsyncCustomNodeManager for server extensibility. The
Migration Guide walks every break in detail, with the
companion 2.0 Migration Analyzer handling most of the mechanical
edits automatically.
Cross-cutting themes
Type system and immutability
The built-in OPC UA types have been redesigned around immutability and
allocation-light value semantics. NodeId, ExpandedNodeId,
QualifiedName, LocalizedText, Variant, ExtensionObject,
DataValue, and ArrayOf<T> are now readonly structs; null checks are
replaced with IsNull / .Null to align with INullable. A new
ByteString is preferred over byte[] in public API, and ArrayOf<T> /
MatrixOf<T> provide first-class array and matrix abstractions. The
object-typed public surface has been replaced with Variant across the
stack and in source-generated code, eliminating boxing in encoders, decoders,
and node-state read/write paths. Equality on ExtensionObject,
StatusCode, and numeric ranges has been tightened, and DateTimeUtc
makes timestamp intent explicit. See the
2.0 migration guide — Improved Type Safety
section for the per-type deltas.
Async, cancellation, and TimeProvider
The server now runs fully on the Task-based asynchronous pattern. The new
AsyncCustomNodeManager is the canonical base
class for NodeManagers and threads CancellationToken through every
service call; built-in managers (CoreNodeManager, DiagnosticsNodeManager,
ReferenceNodeManager) have all migrated to it, and MonitoredNode is
IAsyncNodeManager-aware. A new server-side RequestLifetime propagates
the request-scoped cancellation token through the call stack, so a
client-cancelled request short-circuits cleanly. Synchronous-over-async
patterns have been removed from non-obsolete public APIs. The stack also
adopts System.TimeProvider for all timing primitives, replacing direct
DateTime.UtcNow and Timer use; this is what makes server logic
deterministic under test and tolerant of system-clock changes.
Dependency injection and hosting
The stack now offers a unified
Microsoft.Extensions.DependencyInjection surface:
a single services.AddOpcUa() returns an IOpcUaBuilder, and every feature
library hangs its own .AddXxx(...) extension off it. Servers run as
IHostedServices under the .NET Generic Host; options bind from
Action<T> or IConfiguration; identity providers, certificate manager,
secret store, file system, historian, alarms, and the GDS extensions all
register through the same builder. Alongside DI, a
source-generated fluent server API lets
applications stand up a server from a model design XML with a few
.AddXxx().WithYyy() calls; the
ManagedSession
fluent builder is the equivalent on the client.
Native AOT
The full stack — Core, Types, Client, Server, ComplexTypes, GDS, PubSub, and the source generators — is now Native AOT friendly. Public API avoids reflection paths that require trimming suppression, the source generators emit AOT-clean code, and the reference servers/clients can be published as self-contained single-file native binaries. UANodeSet import/export and the encodeable factory have been reworked to function under AOT, and the test matrix includes AOT smoke tests for each shipped library.
Source generators and modeling
The new source-generation pipeline emits the typical OPC UA boilerplate
from model design XML rather than hand-written code. The
NodeManager generator produces a fully
async, fluent NodeManager skeleton plus typed *State properties for every
node; the DataType generator emits
IEncodeable implementations from POCO classes; and a new generator emits
**typed method proxies on ObjectType**s so callers invoke methods with a
strongly-typed signature rather than a generic Call plus variant arrays.
The encodeable factory build path uses an IEncodeableFactoryBuilder so
factories can be assembled deterministically and AOT-cleanly; OPC UA
OptionSet data types are now backed by generated structures, and
cross-assembly model references are tracked via the
ModelDependencyAttribute. The generator can also
default a model's instance modelling rules to its type-definition rules,
which the stack now opts into. For Optional Variable/Method children
the generator emits five chainable Add{Child} overloads per typed
state class (idempotent ensure-child, Action<TChild> configure,
conditional configure, Func<TChild, TChild> replace, conditional
replace) so opt-in extensions of singleton instances collapse into a
single fluent chain.
OPC UA companion-spec coverage
This release substantially extends companion-spec coverage with full server- and client-side implementations:
- Part 9 — Alarms and Conditions: full server + client implementation
with latched / silenced / out-of-service variants, alarm groups and a
suppression engine, rate metrics, a typed
AlarmClient, theAlarmEventFilterBuilder, andIAsyncEnumerablealarm streaming. See Alarms and Conditions. - Part 11 — Historical Access + Part 13 — Aggregates: a provider
model with an in-memory historian and a
HistoryClientfor raw, modified, at-time, processed, and annotation reads/updates. All 37 standard v1.05.07 aggregate functions, with native push-down where available and a framework fallback otherwise. See Historical Access and Aggregates. - Part 16 — State Machines: a unified fluent
StateMachineBuilderwith both definition (FluentFiniteStateMachineState) and lifecycle (attach behaviour to stack-shipped or generator-emitted FSMs) modes, plus client-side streaming / read helpers on the generated*TypeClientproxies. - Part 17 — Alias Names: full server + client support for
AliasNameType,AliasNameCategoryType,FindAlias,FindAliasVerbose,AddAliasesToCategory,DeleteAliasesFromCategory, andLastChange. See Alias Names. - Part 18 — Role Management: full server-side role administration
surface, with the server automatically assigning the OPC UA Part 3 §4.9
TrustedApplicationrole, and a pluggable identity-provider model that supports anonymous, username, X.509, and token-issuer flows (OAuth2 / OIDC / Entra / JWT). - Part 20 — File Transfer: a server-side FileSystem library, with a
matching System.IO-style
FileSystemClienton the client. - Part 100 — Device Integration: the
Opc.Ua.Di/Opc.Ua.Di.Server/Opc.Ua.Di.Clientlibrary trio with a fluentIDeviceBuilder, device sub-type extensions, lock service, software-update package store, and client helpers. See Device Integration and Software Update. - Parts 210 and 211 — Relative Spatial Location and Global Positioning: source-generated released RSL/GPOS models, standalone and composed server hosting, technology-neutral position providers, typed clients and streams, frame-chain resolution, WGS84/ENU conversion, and rigid/similarity/affine Zone fitting. The robot/OpenUSD sample publishes independently configurable mobile robot poses. See Positioning.
- OPC 40010-1 — Robotics (over OPC 40001-1 — Industrial Automation):
the
Opc.Ua.Robotics/Opc.Ua.Robotics.Server/Opc.Ua.Robotics.Clientlibrary trio over Device Integration, with source-generated Robotics 1.02 and IA models,AddRobotics/ConfigureRoboticshosting, ordered model providers, and validated fluent topology builders that assemble motion device systems, controllers, motion devices, axes, power trains, motors, gears, drives, safety states, and task controls with the correct companion-spec references. See Robotics, including the draft Robot Intent task-level command model. - OPC 10100-1 — WoT Connectivity: model, server, and client libraries
for surfacing OPC UA servers as Web of Things Thing Descriptions, with
the
WoTAssetConnectionManagementserver methods gated by a configurableWotManagementAccessPolicy(defaults:SignAndEncryptchannel +SecurityAdminrole + no anonymous). See WoT Connectivity. - Local Discovery Server: a built-in LDS implementation usable standalone or as part of a hosted server.
Other server-side feature work:
NodeManagement service set (AddNodes,
DeleteNodes, AddReferences, DeleteReferences with an
INodeManagementAsyncNodeManager opt-in and a per-manager
AllowNodeManagement gate),
Model Change Tracking (server-side
ModelChangeAggregator and auto-emitted GeneralModelChangeEvents, with
client-side per-node INodeCache.InvalidateNode), and the
Subscriptions and Monitored Items service set
(V2 subscription engine, declarative + imperative SetTriggering with
N:M support, and IAsyncEnumerable-based streaming subscriptions for
state-machine waits and short-lived monitoring).
Performance, memory, and pooling
The type-system rework eliminates a large class of allocations: every
encode/decode of NodeId, Variant, DataValue, ExtensionObject, and
their collections now stays on the stack or in pooled buffers. A new
IPooledEncodeable activator pool further reduces GC pressure on hot
encode paths. Server-side, MonitoredNode2 caches role-permission
validation event-driven (no more per-publish recomputation), publishing
queues use channel-based consumers, and NodeState.ReadAttributes has
been optimised. Lifetime bugs that surfaced under load were fixed in
several places: socket and event-handler leaks during server restart,
timer leaks in ChannelAsyncOperation.EndAsync, TcpTransportListener
resource leakage in ServerBase.StopAsync, undeleted subscription
diagnostic nodes, and the abandoned-subscription map migrated from a
locked List to a ConcurrentDictionary.
Security and certificates
A new ref-counted Certificate wrapper and the
CertificateManager segregated-interface design replace the older
X509Certificate2 exposure: certificates are tracked deterministically,
shared safely, and disposed predictably across stores, channels, and
identity flows. Secure-channel negotiation has been hardened; the client
now auto-detects and force-renegotiates on server certificate rotation,
and application-certificate lookup can fall back from a concrete
ApplicationCertificateType to the abstract type when no concrete entry
matches. The EncryptedSecret machinery now supports both RSA and ECC and
is bridge-compatible with legacy .NET / OPC UA implementations. The server
ships with client lockout for failed
authentication attempts, and SubCA revocation no longer auto-creates an
empty CRL on the issuing CA.
Cryptography is now pluggable. A CryptoProvider model
lets an application route cryptographic operations to another library, an
offboard service or hardware, chosen per purpose and per security policy and
injected through AddCryptoProvider(…). The default is unchanged and costs
nothing: everything resolves to platform cryptography until something is bound.
Private keys no longer have to be owned by the certificate — a key can be held
detached, in a TPM, a smart card or an HSM, and never enter process memory.
Certificate.CopyWithDetachedPrivateKey is the seam that makes this work on
every platform, which X509Certificate2.CopyWithPrivateKey does not.
The optional OPCFoundation.NetStandard.Opc.Ua.Security.Pkcs11 package adds a
PKCS#11 certificate store addressed by RFC 7512 pkcs11: URIs. Which
cryptographic module performed an operation, and whether it carries any
validation, is auditable through logs, metrics and the address space, and can
be constrained with a compliance policy.
By layer
Server
AsyncCustomNodeManager is now the recommended base for all custom
NodeManagers, and every NodeManager shipped with the stack has migrated to
it. MonitoredNode is IAsyncNodeManager-aware and uses channel-based
queuing under load; events from the server node are dispatched through
multiple channel consumers; role-permission validation is cached
event-driven in MonitoredNode2; and the request queue, event handling,
and publishing path have all been hardened with new test coverage. Server
identity is now pluggable end-to-end (anonymous / username / X.509 / token
issuer) and persistent users are loaded through
IUserDatabase.GetUsers. Per OPC UA Part 3 §4.9 the server assigns the
TrustedApplication role automatically. The
NodeManagement service set, per-NodeManager Allow…
gates, and ModelChangeAggregator round out the server extensibility
surface. The server, the audit/redaction APIs, and the publishing path
have been audited for sync-over-async and converted to TAP. See
Sessions for the matching session-/subscription-engine
story.
Client
The client now offers two coexisting paths. The
classic Session
remains for callers that own session lifecycle. The
new ManagedSession
encapsulates the connection state machine, reconnect policy, and pluggable
subscription engine behind a fluent builder; it is the recommended path for
new code. The V2 subscription engine runs alongside the classic engine
and has feature and test parity with it; an opt-in
SubscriptionRecoveryPolicy lets servers signal Good_SubscriptionTransferred
without surprising the client; and the user
token policy used on Connect is now re-used during Reconnect /
ReactivateSession. Under the hood, a new
IClientChannelManager owns client-side transport channels with
reference counting, sharing, and coalesced reconnect: sessions, discovery
clients, and registration clients targeting the same
ConfiguredEndpoint (with the same reverse-connect identity) share a
single underlying ITransportChannel, reconnect is transparent to
callers, and the previous AttachChannel / DetachChannel +
SessionReconnectHandler patterns are obsoleted. A shared IRetryBudget
collapses the two-level retry deadline so reconnect no longer compounds
multiplicatively. The new
unbounded monitored items feature
transparently shards a V2 ManagedSession subscription across multiple
real server-side Subscription partitions when the server's
MaxMonitoredItemsPerSubscription cap is hit — callers that exceed the
cap continue to succeed instead of failing with
BadTooManyMonitoredItems, and the public ISubscription /
MonitoredItemCollection shape is unchanged. New client-side features
include FileSystemClient (a System.IO-style
async client over OPC UA File methods),
HistoryClient,
AlarmClient, and source-generated typed
ObjectType proxies. Client-side NodeSet export
extracts a server's address space to NodeSet2 XML, and
ModelChangeTracking keeps the local
INodeCache consistent with server-side model changes.
High availability and redundancy
2.0 maps OPC UA Part 4 §6.6 redundancy across the server, client, and network,
and layers an opt-in distributed high-availability story on top. On the server,
AddServerRedundancy(...) publishes the Server.ServerRedundancy nodes, drives
Server.ServiceLevel, advertises the NTRS non-transparent discovery
capability, and exposes RequestServerStateChange for administrator-driven
Maintenance/NoData failover — for every RedundancySupport mode
(None/Cold/Warm/Hot/HotAndMirrored/Transparent). On the client, a single
ManagedSession with WithServerRedundancy() reads that
metadata and fails over transparently, so the same code works whether or not the
server is configured for redundancy.
The new Opc.Ua.Redundancy, Opc.Ua.Redundancy.Server,
Opc.Ua.Redundancy.Client, and Opc.Ua.Redundancy.Kubernetes packages add the
distributed building blocks behind DI/fluent seams. UseDistributedAddressSpace
/ UseReplicatedAddressSpace, UseDistributedSessions /
UseReplicatedSessions, and UseDistributedSubscriptionMirroring mirror
address-space topology and values, session state (fast reconnect that still runs
a full ActivateSession signature re-check against a single-use nonce), and
subscription / retransmission state across replicas. UseRedundancyConsistency
selects the shared store's consistency model — a leaderless CRDT gossip
layer (eventual, active/active) or a linearizable Raft layer
(DefaultRaftConsensus, strong, for single-use nonces and leader election) —
both over the in-package NanoMsg transport, with every record
authenticated-encrypted through IRecordProtector. Address-space hydration uses
a snapshot + delta-log fast path for quick time-to-ready on failover, and an
optional GetEndpoints load-direction seam (UseServerLoadDirection) can steer
clients to the best replica. The default path (no store configured) is unchanged
and zero-overhead. See High Availability for the full
design and Kubernetes for the deployment guide.
Global Discovery Server
The GDS implementation is now full OPC UA Part 12 compliance, including
modern StartRequestToken / FinishRequestToken flows
(AuthorizationService) and the pull/push
KeyCredentialService. The client supports
pushing to arbitrary certificate groups; the server supports custom
certificate groups; SubCAs can be revoked without auto-creating an empty
CRL; and method-call validation is strict. The full developer guide
is in GDS.
Part 14 PubSub modernization
The PubSub stack (Opc.Ua.PubSub, Opc.Ua.PubSub.Udp,
Opc.Ua.PubSub.Mqtt, Opc.Ua.PubSub.Server) is rewritten end-to-end
to track Part 14 v1.05.06.
- Native AOT clean. The combined reference sample
(
ConsoleReferencePubSubClient, withpublisher/subscriber/externalmodes) publishes AOT with zeroIL2026/IL3050;PubSubAotTestsexercises every runtime path under AOT. - DI-integrated.
services.AddOpcUa().AddPubSub(o => …)registers the runtime, scheduler, security subsystem, transports, and SKS into the standardIServiceCollection. SeeDependencyInjection.md. The previous "PubSub is not part of the dependency-injection surface" caveat is removed. - Fluent builder.
PubSubApplicationBuildercomposes connections, groups, writers, readers, transports, and security in code; XML configuration loads through the same builder. Inline construction or fullIPubSubConfigurationStoreround-tripping are equivalent. - Full v1.05.06 spec coverage. UADP (§7.2.4) and JSON (§7.2.5)
encoders/decoders, including
JsonEncodingMode{ Verbose, Compact, RawData },SingleNetworkMessage, Action and Discovery messages; UDP datagram-v2 (DatagramConnectionTransport2DataType+QosCategory→ DSCP), MQTT 3.1.1 + 5.0 with QoS 0/1/2 and retained metadata at startup; SKS pull / push (§8.5.1, §8.5.2); AES-128-CTR and AES-256-CTR with HMAC-SHA-256 (NIST SP 800-38A F.5.1 / F.5.5 KAT-asserted). - Per-component diagnostics. Every connection, group, writer, and
reader now carries its own
IPubSubDiagnosticsinstance, surfaced on the address space whenAddPubSubAddressSpaceis wired. - Runtime configuration mutation.
IPubSubApplication.Add/Remove*methods compose new connections / groups / writers / readers without a stop-reconfigure-restart cycle; the same methods are bound to the Part 14 §9PublishSubscribeObject methods. - Security wiring.
UadpSecurityWrapperis now invoked at send / receive; configurations that named aSecurityModeother thanNoneactually get that security applied. - Retained metadata.
MetaDataPublisheradvertises every activeDataSetMetaDataonce at startup (UDP discovery / MQTT retained topic) so subscribers that join mid-stream can decode RawData. - MQTT 3.1.1 + 5.0. The MQTT transport uses
MQTTnetv4 on net48 / netstandard and v5 on net8 / 9 / 10. Certificate authentication per Part 14 §6.4.2.2.4 is supported.
For library reference and code samples, read PubSub.md.
For the upgrade story (breaking changes, compatibility matrix, and
codemod recipes), read
migrate/2.0.x/pubsub.md.
Tooling
A new MCP server (see MCP Server) exposes OPC UA client
operations as Model Context Protocol tools, so an LLM or Copilot can
browse, read, write, subscribe, and call methods on any OPC UA server.
The MCP server additionally ships packet-capture, packet-decode, and
packet-replay tools so the agent can capture a UA-TCP exchange to
PCAP, inspect the decoded service calls, and replay them — useful for
reproducing interop issues without re-running the original client. A
2.0 Migration Analyzer + code fixer ships as a Roslyn analyser package
(OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer) that detects the
typical 1.5.378 → 2.0 patterns and applies most of the mechanical edits
automatically; see the Migration Guide for the
opt-in workflow.
Build, CI, and observability
The build pipeline now runs on a managed DevOps pool with a per-TFM
build/test matrix and parallelized client tests. Nullable is enabled
across src/, the nine src/, and the samples/ projects;
dispose-analyzers (CA2000, CA2213) are on and clean. The repository
follows a strict dotnet format baseline (whitespace, IDE, RCS) enforced
by the opc-ua-codestyle-enforcer agent. Code analysis runs at "preview"
level with "all" mode, package validation is on, and treat-warnings-as-
errors is set repo-wide. On the runtime side,
Diagnostics is plumbed through ITelemetryContext:
loggers, meters, and activities all hang off the same context object, and
log redaction is wired through the audit APIs. Tests have been
reorganised for faster CI, with several integration suites separated from
unit suites, and code-coverage gates apply to all non-test, non-application
projects. Those gates now run inside the pipeline itself - an absolute
project floor plus a changed-lines check - instead of relying on an external
coverage service; see
Continuous integration.
Further reading
- Migration Guide — prescriptive, per-API migration reference from 1.5.378 to 2.0.
- Profiles — supported OPC UA profiles, facets, and security policies in 2.0.
- Sessions, Reconnection, and Subscription Engines —
architectural overview of
SessionvsManagedSessionand the classic vs V2 subscription engines. - High Availability and Redundancy — OPC 10000-4 §6.6
server/client/network redundancy and the opt-in distributed HA building
blocks; Kubernetes High Availability Deployment — the
Kubernetes deployment guide for the
Opc.Ua.Redundancy.Kubernetespackage. - Dependency Injection, Native AOT, Diagnostics, Source-Generated NodeManagers, Source-Generated DataTypes.
- Companion specs: Alarms and Conditions, Historical Access, Aggregates, State Machines, Alias Names, Device Integration, Relative Spatial Location and Global Positioning, Software Update, WoT Connectivity, Subscriptions and Monitored Items, Node Management, Model Change Tracking, Model Dependencies.
- Security, identity, and certificates: Certificates, Certificate Manager, ECC Profiles, Role-Based User Management, Identity Providers, Authorization Service, Key Credential Service, GDS Developer Guide.
- Client features: File System Client, NodeSet Export, Complex Types, Transfer Subscription, Reverse Connect, Durable Subscription.
- Tooling: MCP Server, Container Reference Server, Provisioning Mode.
- PubSub: PubSub library.