Skip to main content
A decide call sits in the path that renders your content. Curious is designed so that nothing on its side can break that path, but the guarantee is only as good as the client: every call needs a deadline and something to show when the deadline passes. The server SDK does both by default; this page is what it does, so you can do the same anywhere.

The deadline

Pick a deadline you can afford in the render path and enforce it on the client. The server SDK’s default is 1.5 seconds; the browser SDK’s is 1 second, and lower is allowed. When it passes, abort the request and serve the fallback. A decision that arrives after you rendered is of no use to the user, and it still counts as a decision on our side, so do not wait for it.

The fallback

The fallback is your control: the content you would show without Curious. It is the same thing you declared as control, which is why the SDK’s decide() takes a required fallback and the browser SDK uses the page’s own text. Serve it when:
  • the deadline passes;
  • the call fails with any status, including a 409 or a 5xx;
  • the response does not have the shape your renderer expects.
A user who sees the fallback sees your production content. The only cost is a decision that was not recorded, which is learning, not revenue.

No retries without a key

A decide is a write: it records which arm the user saw, and a second decision for the same user and element ends the first one’s window. A retry after a timeout or an ambiguous failure therefore risks a second decision. Either do not retry (the SDK’s choice), or generate an idempotency_key before the first attempt and send the same key on the retry, which replays the original decision if it committed and makes a fresh one if it did not. See Idempotency.

Where to call decide

Call decide on the server when you can: the key stays secret, the user’s attributes are at hand, and the deadline competes with nothing else in the browser. Call it from the browser with a publishable key when the content is rendered client-side and the element is already declared. In both cases, call it once per exposure and reuse the result for that exposure; see Assignment and stickiness.

Measure the fallback rate

Record how often you served the fallback and why. The SDK’s result carries served: "curious" | "fallback", error.code (timeout, network_error, server_error, content_shape_mismatch, …) and the requestId to quote to support. A rising fallback rate is the signal that a deadline is too tight for a cold runtime, that a key was revoked, or that the shape of a declared format and the renderer have drifted apart.

With the server SDK

decide() never throws by default and never retries. Set decideTimeoutMs to change the deadline. See Decide with the server SDK.

Without an SDK

Use your HTTP client’s timeout, catch every failure, and serve the control. The behaviours to reproduce are listed on Raw HTTP. Next: the go-live checklist. If the fallback keeps serving, see The SDK keeps serving the fallback.