Skip to content

Configuration

Configure query behavior centrally through the <Arc /> component instead of per query instance.

PropTypeDefaultPurpose
microservicestringundefinedRoutes query requests to a named microservice in shared-ingress environments.
apiBasePathstring''Prepends a base API path to query requests.
httpHeadersCallback() => HeadersInitundefinedAdds dynamic headers (auth, cookies, custom headers) to query requests.
queryTransportMethodQueryTransportMethodServerSentEventsSelects SSE or WebSocket transport for observable query connections.
queryDirectModebooleanfalseBypasses centralized hubs and connects observable queries directly per query URL.
queryConnectionCountnumber1Number of observable query hub connection slots.
observableQueryTransferModeObservableQueryTransferModeDeltaControls how useChangeStream() processes incoming snapshots and deltas.
queryCacheRetentionMsnumber30000How long to keep cached query data alive after the last subscriber unmounts.
eventSourceFactory(url: string) => EventSourceundefinedCustom factory for creating the EventSource instances used by SSE observable query connections. Falls back to the global EventSource constructor when not set.
import { Arc } from '@cratis/arc.react';
import { ObservableQueryTransferMode } from '@cratis/arc';
import { QueryTransportMethod } from '@cratis/arc/queries';
export const App = () => (
<Arc
microservice="my-app"
apiBasePath="/api"
queryTransportMethod={QueryTransportMethod.ServerSentEvents}
queryDirectMode={false}
queryConnectionCount={1}
observableQueryTransferMode={ObservableQueryTransferMode.Delta}
httpHeadersCallback={() => ({ Authorization: `Bearer ${getToken()}` })}
>
<MyRoutes />
</Arc>
);

When a component that uses useObservableQuery unmounts — for example, when the user navigates to a different page — Arc holds the cached query data and the active server subscription alive for queryCacheRetentionMs milliseconds (default: 30 seconds) before evicting them.

This has two practical effects:

  • Instant navigation: If the user returns to the same page within the retention window, cached data renders immediately instead of showing a loading state while the subscription re-establishes.
  • Bounded memory: After the window expires, the cache entry and the underlying connection are released automatically, so long-lived single-page applications do not accumulate stale subscriptions.
<Arc queryCacheRetentionMs={60_000}>
{/* data survives for 60 s after the last subscriber unmounts */}
</Arc>

Set the value to 0 to restore the previous behavior of evicting the subscription as soon as the last subscriber unmounts:

<Arc queryCacheRetentionMs={0}>
{/* immediate eviction — original behavior */}
</Arc>

The default can also be adjusted globally without the React component:

import { Globals } from '@cratis/arc';
Globals.queryCacheRetentionMs = 60_000;

Note: The retention window applies per cache entry, not globally. Each query type and argument combination has its own independent timer.

Use queryTransportMethod, queryDirectMode, and queryConnectionCount to control observable query connection behavior.

For transport semantics, hub behavior, SSE limits, and pooling details, see Observable Query Multiplexing.

By default, SSE observable query connections create their transport with the global EventSource constructor. Some environments either lack a native EventSource — React Native does not ship one — or ship one with unreliable streaming behavior. JS-based polyfills built on XMLHttpRequest are known to deliver messages in bulk instead of streaming them, silently drop connections when the app is backgrounded, and provide no reliable way to detect a dead connection on Android.

Set eventSourceFactory to substitute your own SSE client without changing anything else about how observable queries work:

import { Arc } from '@cratis/arc.react';
import RNEventSource from 'react-native-nitro-sse';
export const App = () => (
<Arc eventSourceFactory={(url) => new RNEventSource(url)}>
<MyRoutes />
</Arc>
);

The factory receives the fully-qualified connection URL and must return an object implementing the standard EventSource interface (onmessage, onerror, close(), readyState). This applies to both direct-mode and hub-mode SSE connections.

The default can also be set globally without the React component:

import { Globals } from '@cratis/arc';
Globals.eventSourceFactory = (url) => new RNEventSource(url);

observableQueryTransferMode sets the global default for useChangeStream() processing.

ValueBehavior
ObservableQueryTransferMode.DeltaUses server-provided ChangeSet when available and falls back to client-side diffing.
ObservableQueryTransferMode.FullTreats every snapshot as a full batch of additions.

For hook-level behavior, see Change Stream.