---
title: Queries
description: Read application state once or observe updates with standalone Arc.
---

<!-- Copyright (c) Cratis. All rights reserved.
Licensed under the MIT license. See LICENSE file in the project root for full license information. -->

A screen needs a list, a detail view, or a dashboard—not another hand-written API client. Arc lets you declare the read, expose it through HTTP, and generate a typed TypeScript proxy for the frontend.

Queries read **application state**. That can be a MongoDB document, an EF Core entity, data from a service, or an in-memory model. **Arc queries do not require Chronicle or event sourcing.** A database query or MongoDB `Observe()` call is not a Chronicle projection. If your application optionally uses Chronicle, its projected read models can be queried too; see [Chronicle integration](/arc/backend/csharp/chronicle/).

## Choose a declaration style

| Style | What you write | Choose it when |
| --- | --- | --- |
| [Model-bound](/arc/backend/csharp/queries/model-bound/) | Static query method on the `[ReadModel]` type it returns | You want the query next to its data shape with minimal endpoint boilerplate |
| [Controller-based](/arc/backend/csharp/queries/controller-based/) | MVC GET action | You need MVC route-value/DTO binding, filters, or HTTP response control |

The two paths share result rendering but **not all binding, validation, or authorization behavior**. Start with the model-bound example, then use the controller path deliberately where its contract fits better.

## Request once or observe updates

```mermaid
flowchart LR
    UI[Client] -->|GET / QUERY / subscribe| Arc[Arc endpoint]
    Arc --> Query[Query method]
    Query --> State[(Application state)]
    State --> Producer[Optional observable producer]
    Query -->|one result| UI
    Producer -->|streamed results| UI
```

| Mode | Behavior | Use it for |
| --- | --- | --- |
| Request/response | Read once through GET or [generated HTTP QUERY](/arc/backend/csharp/queries/using-the-http-query-method/) | One-off reads and reports |
| [Observable](/arc/backend/csharp/queries/model-bound/observable-queries/) | Subscribe to a producer over SSE/WebSocket | Lists or dashboards that should stay current |

An observable query needs a producer that detects changes; a return type alone does not watch your database. Arc's MongoDB integration supplies `Observe()`. Other providers need their own observation mechanism. An update may follow a [command](/arc/backend/csharp/commands/) changing database state directly, or an optional Chronicle projection updating it.

## Learn the contract in order

1. [Declare a model-bound read](/arc/backend/csharp/queries/model-bound/), then add [arguments](/arc/backend/csharp/queries/model-bound/query-arguments/).
2. Apply [validation](/arc/backend/csharp/queries/validation/) and [authorization](/arc/backend/csharp/queries/model-bound/authorization/), including their current limitations.
3. Read the [QueryResult contract](/arc/backend/csharp/queries/query-pipeline/#query-result-metadata) and add [paging](/arc/backend/csharp/queries/model-bound/paging/).
4. Expose [observable updates](/arc/backend/csharp/queries/model-bound/observable-queries/) and understand subscription disposal.
5. For advanced delivery, use the [hub protocol](/arc/backend/csharp/queries/observable-query-demultiplexer/), [change streams](/arc/backend/csharp/queries/change-stream/), and [emission guards](/arc/backend/csharp/queries/observable-query-emission-guards/).

[Read-model interception](/arc/backend/csharp/queries/read-model-interception/) transforms supported result paths, but currently excludes observable HTTP snapshots. [Query health](/arc/backend/csharp/queries/query-health/) helps diagnose hub subscriptions but exposes sensitive telemetry unless you restrict it. Use [cURL workflows](/arc/backend/csharp/queries/using-observable-queries-with-curl/) to distinguish a snapshot from a live stream.

## Consume the read in React

A successful backend proxy-generation build supplies typed client declarations. Use the generated query's hook and result state instead of maintaining a separate transport model. Continue with [queries in React](/arc/frontend/react/queries/) and [proxy generation](/arc/backend/csharp/proxy-generation/).
