> ## Documentation Index
> Fetch the complete documentation index at: https://docs.insito.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Throttling

> How Insito decides not to interrupt the same user too often.

Throttling stops Insito from interrupting a user again too soon after a survey
was shown. The default is **7 days**, and it applies **per project, per user** —
not per survey. Once any survey is shown to a user, that user won't be shown
another survey in the same project until the window elapses.

## How the window works

Throttling is enforced in Redis:

1. When a survey modal is shown, the SDK calls `POST /v1/sdk/impression`. The API
   writes a key `throttle:<projectId>:<userId>` with a TTL of
   `throttle_days × 86,400` seconds (the shown survey's window).
2. On every `POST /v1/sdk/event` and `POST /v1/sdk/evaluate`, the API checks
   whether that key exists **before** any survey matching. If it exists, the API
   returns `survey: null` and the SDK silently returns to `idle`.

Because the key isn't scoped to a survey ID, showing **any** survey throttles
the user against **all** surveys in the project until the TTL expires.

Implications:

* An **impression** (modal shown) is what starts the window — not the response.
  A user who closes the modal without answering is still throttled.
* A **failed or abandoned response** doesn't undo the throttle: if the modal was
  shown, the impression already set the key.
* The window length is taken from the survey that was actually shown, so if two
  surveys have different `throttle_days`, the one shown wins for that user.

## Tuning the window

In the survey builder, open the **Trigger** tab and set **Minimum days between
shows** (the `throttle_days` field). Range is 0–365; the default is **7**.
Setting it to `0` disables throttling for that survey (useful for testing). It
takes effect on the next `event`/`evaluate` call.

Recommended settings:

| Scenario                                 | Days between shows | Rationale                                          |
| ---------------------------------------- | ------------------ | -------------------------------------------------- |
| Standard NPS                             | 30                 | Common recurrence window; users won't feel nagged. |
| Beta funnel                              | 7 (default)        | Faster iteration on small cohorts.                 |
| Manual feedback ("Send feedback" button) | 1                  | User-initiated, mostly self-throttling.            |
| Onboarding survey                        | 90                 | One-time moment; a long window avoids re-asking.   |

## Per-survey show caps

Separately from the project-wide time window, a survey can cap how many times it
is ever shown to one user via the **frequency → max shows per user** setting.
The API counts rows in the `impressions` table for that `(survey, respondent)`
and stops matching once the cap is reached. Use this for "show this at most
twice, ever" rules that a time window can't express.

## Cross-survey behaviour

Since the throttle key is project-wide, two different surveys **cannot** both
fire on the same user within the window — the first one shown blocks the rest.
If you need surveys that can interleave more freely, keep their windows short or
use separate projects.

## Testing without waiting

There's no "reset throttling" button in the dashboard. To iterate during
development:

1. Set the survey's **Minimum days between shows** to `0`.
2. Pass a fresh `userId` to `MicroSurvey.identify()` each test session.
3. Or use a separate test project (its own API key).

<Note>
  Redis failures are non-fatal: if the throttle check can't reach Redis, the API
  treats it as "not throttled" and continues evaluating, and a failed impression
  write still returns `200` (the `impressions` row is the source of truth).
</Note>
