Skip to content

Observable Queries

Observable queries provide real-time updates in React through useObservableQuery() and generated proxy helpers. Arc supports both centralized hub routing and direct per-query connections.

For backend implementation patterns, see Controller-based Observable Queries, Model-bound Observable Queries, and Observable Query Hub.

By default, observable queries connect through centralized hub endpoints. Two props on the <Arc> component control this behavior.

Selects the transport protocol used for the hub connection.

ValueDescription
QueryTransportMethod.ServerSentEventsShared SSE hub at /.cratis/queries/sse, with subscribe/unsubscribe POSTs (React default).
QueryTransportMethod.WebSocketWebSocket hub transport.
import { Arc } from '@cratis/arc.react';
import { QueryTransportMethod } from '@cratis/arc/queries';
export const App = () => (
<Arc
microservice="my-app"
queryTransportMethod={QueryTransportMethod.ServerSentEvents}
>
<MyRoutes />
</Arc>
);

Controls whether observable queries connect directly to each query’s own URL or route through the centralized hub.

  • When false (default): queries are routed through the centralized hub endpoint (/.cratis/queries/sse or /.cratis/queries/ws depending on queryTransportMethod).
  • When true: each observable query opens its own connection directly to the per-query URL, bypassing the hub entirely. This is useful during local development or when connecting to services that do not expose the centralized hub.
import { Arc } from '@cratis/arc.react';
export const App = () => (
<Arc
microservice="my-app"
queryDirectMode={true}
>
<MyRoutes />
</Arc>
);
PropTypeDefaultDescription
queryTransportMethodQueryTransportMethodServerSentEventsTransport used for observable query connections.
queryDirectModebooleanfalseWhen true, bypasses the hub and connects directly per query.

Non-Suspense observable hooks select a cache entry by query, arguments, page, page size and sort order. Changing any of these selects a matching subscription or starts one with the new settings. Two consumers on different pages do not share a subscription; matching consumers do.

The result immediately shows the matching entry’s cached result, if one exists. Otherwise it resets to the query’s default value with isReady: false and isPerforming: true until a result arrives. Rows and failure status from the previous entry are not shown as the new result, and later pushes to the previous subscription do not update the component.

A retained subscription stays live during the cache retention window. Returning to it shows its latest cached result without another subscribe. See query instance caching for retention settings and paging for the paging and sorting controls.

For both SSE and WebSocket hub connections, a server Error message delivers a query result with isReady: true, isSuccess: false, hasExceptions: true, and the server error in exceptionMessages. For example, a MongoDB collection watch that cannot start because the database is unreachable reports a failure instead of leaving the hook waiting for its first result.

Check result.hasExceptions and show the error before treating missing data as an empty result. Normal unsubscribe and watch cancellation do not produce error results. An error result does not itself restart a failed backend observation; recovery requires a new observation. See MongoDB observation errors and recovery limits.