Skip to content

Concepts

The vocabulary used across the platform. Each section is a survey — the formal definition lives in the OpenSpec.

gRPC (mirrored invocation)

gRPC is the inter-service wire protocol. Every backend service exposes a gRPC interface; the API gateway discovers that interface via gRPC reflection and proxies calls to it. Clients do not need the backend's .proto files at compile time — they call by service and method name through the gateway.

  • Why Virtufin uses it: one wire protocol for all backends, one client library per language, streaming for free, native integration with the reflection-based gateway.
  • See Cross-cutting spec for the platform-wide rules.

Dapr

Dapr is the sidecar that Virtufin uses for pub/sub, state, and service-to-service invocation. The Virtufin services do not talk to NATS / Redis / a KV store directly — they talk to Dapr, and Dapr talks to the backend. This is why the API gateway can swap brokers without changes to the calling code.

  • Why Virtufin uses it: portable infra (Dapr runs on K8s, docker compose, bare metal, and a sidecar-less in-process mode), one API for pub/sub + state + service invocation, and no bespoke SDK per language.
  • See Cross-cutting spec.

Pub/Sub (CloudEvents 1.0)

All inter-service events are CloudEvents 1.0 envelopes. Producers publish via the Pubsub.PublishEvent RPC on the API gateway; consumers subscribe via Pubsub.Subscribe (server-streaming) or Pubsub.PublishEvent (with a response_topic for request/response patterns). The gateway is the only service that talks to the Dapr pub/sub directly.

  • Why Virtufin uses it: CloudEvents is the lingua franca for event metadata (source, type, subject, time), CloudEvents 1.0 has implementations in every target language, and routing on ce-type + subject is the unit of subscription.
  • See pubsub-topics spec for the topic naming scheme.

Lanes & scenarios (event routing)

Two orthogonal axes split the event stream into addressable topics:

  • Market-data laneact.exchange.<venue>.<entity>.<event>[.<id>] for live data, hyp.<selector>.exchange.<venue>.<entity>.<event>[.<id>] for historical replays.
  • Scenario lanesc.<scenarioId>.<domain>.<entity>.<event>[.<id>] for strategy / position / P&L / risk events that depend on a triplet of (market data, portfolio, strategy) state.

The reserved scenario id LIVE is the production scenario and is auto-seeded at service start with the {act, act, act} triplet. A backtest registers its own scenario id and replays the same market data stream with a different time clock.

  • Why Virtufin uses it: the same producer code can target production and backtest by changing one address. A new selector (a new data universe) is a topic addition, not a code change.
  • See pubsub-topics spec and scenarios spec.

State (distributed KV)

State is a flat key-value store, partitioned by service name. The State.* RPCs on the API gateway are the only interface; each service sees its own namespace (State.SaveState(service: "websocketmanager", ...)). The gateway handles ETag-based conflict detection and forwards to Dapr's state API.

  • Why Virtufin uses it: services do not own storage. The gateway's state is a generic KV; the Dapr sidecar talks to whatever backing store is configured (Redis, Cosmos, Postgres, in-memory for tests).
  • See Cross-cutting spec.

Workers

A worker is a piece of code that subscribes to events (or accepts commands) and produces events back. The WorkManager loads workers via pluggable engines and dispatches incoming events to them. The wire protocol is fixed by the worker-management spec.

  • Why Virtufin uses it: strategy code is a unit of deployment, not a service. A new strategy does not require a new gRPC service, a new proto, or a new deploy. It is a file in a workers repo, loaded at startup.
  • See Worker DevKit for the writing side.

Engines

An engine is the loader. The WorkManager supports four:

MIME type Engine Process model
text/x-csharp CSharpSourceEngine in-process (Roslyn compile)
application/x-dotnet-dll DotNetDllEngine in-process (CoreCLR via libhostfxr)
text/x-python PythonEngine out-of-process subprocess
application/x-native-dll NativeDllEngine in-process (C/C++/Rust shared library)
  • Why Virtufin uses it: the strategy language is a choice for the strategy author, not a constraint of the platform. In-process is the default because it has the lowest latency and the simplest deploy.
  • See engines spec.

NativeAOT

The .NET services (virtufin-api, virtufin-websocketmanager, virtufin-workmanager) are compiled to native binaries with NativeAOT. No JIT, no runtime install, no warm-up.

  • Why Virtufin uses it: consistent resource profile with the Python and native workers, sub-100ms cold start for autoscaling, fewer moving parts in production.
  • See Cross-cutting spec.

CloudEvents 1.0 (envelope)

The wire format for every event. The Virtufin-specific extensions live in the same envelope: correlationid, scenarioid, runid, exchange, clocktype (wall / historical), eventtime, walltime, market.lane, market.selector, portfolio.lane, strategy.lane.

  • Why Virtufin uses it: the metadata is the contract. A consumer can route on clocktype=historical to filter out production-only paths, or on scenarioid=backtest-42 to isolate a single backtest's outputs.
  • See pubsub-topics spec.