WitRPC separates what you say from how it travels. The service contract stays the same while you choose a transport (how bytes move between client and server) and a serializer (how objects become bytes). This page walks through the options and how to combine them.

Supported transports

Memory-mapped files

Two processes on the same machine exchange data through a shared memory region, bypassing the network stack entirely. This is the fastest option for local IPC and suits one-to-one links moving large volumes of data, such as a host process feeding a compute worker. The limits follow from the design: single machine only, and best used for one server with one client. When several local clients must connect, use named pipes instead.

Named pipes

The operating system's IPC channel: a server creates a pipe by name, and multiple local clients connect to it. Named pipes are fast, reliable, and stay inside the OS without touching the network stack. They are the default choice for local IPC with more than one client, or whenever you want OS-level access control on the channel. Cross-machine pipes exist on Windows but are rarely worth the configuration effort; for anything beyond one machine, use TCP.

TCP

The general-purpose network transport. The server binds a port, clients connect by host and port, and the connection carries reliable, ordered, bidirectional traffic. Use it for anything cross-machine: services on a LAN, a desktop application talking to a remote server, machine-to-machine links over the internet. Plain TCP carries no security of its own; on untrusted networks enable TLS (WithTcpSecure) or WitRPC's message-layer encryption, described in Security & Authentication →.

WebSocket

A full-duplex channel that starts as an HTTP request, which makes it the transport for browsers and restrictive networks. Traffic flows through standard HTTP(S) ports, so it passes proxies and corporate firewalls that would block arbitrary TCP. After the handshake, performance is close to raw TCP. This is the transport for Blazor WebAssembly clients and for any environment where opening custom ports is not an option. Use wss:// (with an https:// listener and a certificate on the server) in production.

REST

The service exposed as stateless HTTP endpoints: each call is an ordinary HTTP request, each response an ordinary HTTP response. Anything that can speak HTTP can call the service, from a Python script to an IoT device, which makes REST the interoperability door for non-.NET clients. The trade-off is fundamental: no persistent connection means no server push, so events do not reach REST clients in real time. Use it for request-reply integrations, not for interactive scenarios.

Configuring transports

Each transport ships as its own NuGet package with builder extension methods.

Memory-mapped file. Server: options.WithMemoryMappedFile("MapName", size) (size in bytes; an overload without size uses the default). Client: options.WithMemoryMappedFile("MapName"). Names must match.

Named pipe. Server: options.WithNamedPipe("PipeName", maxNumberOfClients). Client: options.WithNamedPipe("PipeName").

TCP. Server: options.WithTcp(port, maxNumberOfClients). Client: options.WithTcp("host", port).

TCP with TLS. Server: options.WithTcpSecure(port, maxNumberOfClients, certificate) with an X509Certificate. Client: options.WithTcpSecure("host", port, targetHost, sslValidationCallback), where targetHost must match the certificate name and the callback can be null to use standard validation (or a custom RemoteCertificateValidationCallback for self-signed certificates in development).

WebSocket. Server: options.WithWebSocket("http://localhost:5000/path", maxNumberOfClients); the server upgrades HTTP requests at that URL. Client: options.WithWebSocket("ws://localhost:5000/path"). Schemes pair up: http:// with ws://, https:// with wss://.

REST. REST uses dedicated builders rather than the standard ones: the server is built with WitServerRestBuilder.Build(options => { options.WithUrl("http://localhost:5000/api/"); options.WithService(...); }), and .NET clients use WitClientRest. Non-.NET clients simply issue HTTP requests against the endpoint. REST works with JSON serialization.

Serialization formats

Client and server must use the same serializer; the format is set with one builder call on each side.

JSON (WithJson()) is the default: human-readable, universally understood, ideal while developing and debugging, and required for REST interoperability. Payloads are larger and parsing is slower than any binary option.

MessagePack (WithMessagePack()) is a compact binary format, substantially faster and smaller than JSON, and it serializes ordinary public members without extra attributes in most cases. This is the easy performance upgrade when both sides are .NET.

MemoryPack (WithMemoryPack()) is usually the fastest option: a source-generated, near-zero-overhead binary serializer. It requires marking data types as [MemoryPackable] and partial, so it fits internal systems where you control every DTO and want maximum speed.

ProtoBuf (WithProtoBuf(), via protobuf-net) brings Protocol Buffers' compact payloads and explicit, versioned schemas. Types need [ProtoContract] and [ProtoMember(n)] annotations (or classes generated from .proto files). Choose it when your ecosystem already standardizes on ProtoBuf or when strict schema versioning across teams matters more than raw speed.

Choosing the right combination

High-performance IPC on one machine. Memory-mapped file + MemoryPack for a single client at maximum speed; named pipes + MessagePack when several local clients connect to one server. Both avoid the network stack entirely and outperform any TCP-based setup locally.

Cross-machine, LAN or WAN. TCP + MessagePack is the workhorse. Add security to match the network: WitRPC encryption inside a trusted perimeter, TLS (WithTcpSecure) or WebSocket over wss:// across untrusted networks.

Browser and web clients. WebSocket, with wss:// in production. JSON is the natural format when JavaScript is involved; a Blazor WebAssembly client using the WitRPC client library can use MessagePack for efficiency.

External integrations. REST + JSON opens the service to any language for request-reply calls. If external parties need real-time events, point them at a WebSocket endpoint instead; if they already live on Protocol Buffers, ProtoBuf over TCP or WebSocket keeps the schemas shared.

Whatever the combination, the rule is symmetry: transport and serializer must match on both ends, and security settings along with them. Measured comparisons of these transports and serializers, against each other and against other frameworks, are in Comparing RPC Frameworks in .NET Applications →.