Skip to content

Queries

If commands are how your system changes, queries are how it’s read. A query pulls data out and shapes it for a caller — a list, a detail view, a dashboard. Arc takes the same approach it does for commands: you express the read, and it handles parameter binding, validation, authorization, and a typed TypeScript proxy for the frontend. No hand-written API client, no untyped JSON.

And queries have a superpower commands don’t: they can be observable. An observable query holds a live connection and pushes fresh results to the client whenever the underlying data changes — so a React list re-renders the moment a command updates the read model behind it.

GET / subscribe

binds + validates

reads

result / live stream

React UI

Arc endpoint

Query

Read model

StyleWhat it looks likeReach for it when
Model-boundA read method declared on the model, discovered by conventionThe default. Least boilerplate; the query lives with the data it reads.
Controller-basedA query method on a controllerYou need full control over the HTTP route, or you’re integrating with existing controllers.

A controller-based read is as plain as it looks:

[HttpGet("starting-with")]
public IEnumerable<DebitAccount> StartingWith([FromQuery] string? filter) =>
_collection.Find(Builders<DebitAccount>.Filter.Regex(
"name", $"^{filter ?? string.Empty}.*")).ToList();

Parameters you declare ([FromQuery], route values) become typed arguments on the generated proxy — so the frontend calls StartingWith.use({ filter: '' }) with the compiler checking the shape.

This is the choice that defines a query:

Request / responseObservable
BehaviorFetch once, return a resultSubscribe; results push on every change
TransportA normal HTTP GETSSE or WebSocket, hub-routed by default
Use it forOne-off reads, reports, exportsAnything a user watches — lists, dashboards, status

Favor observable queries for screens that should stay current. The live loop — a command changes state, the read model updates, every subscribed browser re-renders — is the experience Arc is built to make effortless. In a Chronicle-backed slice that state change is an appended event and a projection; in a current-state slice it can be a MongoDB document or EF entity changing directly.

Every query runs through a pipeline where Arc applies the cross-cutting concerns for you:

ConcernPage
How a query is processed end to endQuery Pipeline
Validate query parametersValidation
Authorize by role or policyAuthorization
Transform read models before they’re served (mask, decrypt, enrich)Read Model Interception
Stream many live queries over one connectionObservable Query Hub
Debug a live query from the terminalUse Observable Queries with cURL

As with commands, building the backend generates a typed proxy for every query. From React you call its .use() hook and get back a strongly-typed result with its loading and validation state — see Queries in React. One definition, read safely from C# all the way to the component.