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

# Silent mode

> Run additional anti-fraud services in Silent mode alongside your Primary service to compare and migrate without enforcing their decisions

## Overview

Silent mode lets you run one or more anti-fraud services *alongside* your Primary service without enforcing their decisions. Whenever a Flow rule triggers an anti-fraud check, Silent services are evaluated alongside the Primary, return decisions, and write transaction history events — but those decisions never reject, step up, or otherwise affect the customer's flow.

This is the recommended way to:

* **Warm up a new service.** Let it gather data and tune its models on real traffic before you switch over.
* **Validate a new service before switching over.** Compare its decisions against your Primary in the dashboard.
* **Decommission an old service gradually.** Keep the outgoing service in Silent mode for monitoring after switching to a new Primary.

## Connection modes

Each configured service is in one of three modes (see [Anti-fraud overview](/guides/features/anti-fraud/overview#connection-mode)):

| Mode         | Receives traffic?                   | Decision enforced? |
| :----------- | :---------------------------------- | :----------------- |
| **Primary**  | Yes (when an anti-fraud check runs) | Yes                |
| **Silent**   | Yes (when an anti-fraud check runs) | No (logged only)   |
| **Inactive** | No                                  | —                  |

Exactly one service can be Primary at a time. Any number of services can be Silent.

## How it works

Anti-fraud services are only called when a Flow rule that depends on an anti-fraud score or decision triggers for a transaction (see [Anti-fraud overview](/guides/features/anti-fraud/overview#how-does-it-work)). When that happens:

* The Primary service is called **synchronously** so its decision can be evaluated against your Flow rules.
* Each Silent service is called **asynchronously** via the message queue, so it never adds latency to the transaction.
* All checks (Primary and Silent) are stored against the transaction. The dashboard surfaces every Silent decision as a transaction history event so you can compare side-by-side without affecting the customer.
* If a webhook arrives for a Silent service (for example, a Cybersource Decision Manager review status change), the corresponding check is updated, but no further action is taken on the transaction.

## Fingerprinting with multiple services

<Info>
  No matter how many anti-fraud services you have configured (Primary + any number of Silent), your integration only ever passes **one** device fingerprint value per transaction. There is **no** per-provider fingerprint field.
</Info>

A single shared fingerprint identifier per session is used to seed the fingerprinting library of *every active provider* — that is, the Primary and any Silent services (Inactive services receive no traffic and are skipped). Each provider registers that identifier under its own session/device key. At transaction time you submit the identifier once, on [`anti_fraud_fingerprint`](/reference/transactions/new-transaction#body-anti-fraud-fingerprint), and the platform forwards it to the Primary and each Silent service using whatever per-provider mapping that connector defines. See each connector's documentation for the specific field it expects.

### End-to-end flow with Embed (Primary + Silent)

```mermaid theme={"system"}
sequenceDiagram
    participant Browser as Customer browser (Embed)
    participant FJS as Gr4vy /f.js
    participant ACDN as Provider A CDN
    participant BCDN as Provider B CDN
    participant API as Gr4vy Transactions API
    participant Q as Async queue
    participant A as Provider A Decision API
    participant B as Provider B Decision API

    Browser->>FJS: GET /f.js
    FJS-->>Browser: loader (one shared seed + per-service loaders)
    Browser->>ACDN: Provider A fingerprint script (seeded with shared id)
    Browser->>BCDN: Provider B fingerprint script (seeded with shared id)
    Note over ACDN,BCDN: Both providers now hold the same identifier.
    Browser->>API: POST /transactions { anti_fraud_fingerprint: id }
    API->>A: Decision call (id) — synchronous
    Note over API,A: Provider A — Primary, enforced by Flow rules
    API->>Q: Enqueue Silent decision (id)
    Q-->>B: Decision call (id) — asynchronous
    Note over Q,B: Provider B — Silent, logged only, no added latency
```

When you use Embed (web or mobile), this happens automatically — adding a Silent service requires no code changes in your integration.

If you don't use Embed, see [Automatic anti-fraud device fingerprinting](/guides/features/anti-fraud/fingerprint) for how to load `f.js` yourself or how to seed the same identifier into native mobile SDKs.

## Migration pattern

The intended migration playbook for switching from one anti-fraud provider to another:

<Steps>
  <Step title="Add the new provider as Silent">
    Configure the new provider in the dashboard with connection mode set to **Silent**. Your existing Primary keeps enforcing decisions; the new provider starts collecting data and emitting decisions side-by-side.
  </Step>

  <Step title="Compare in the dashboard">
    Review the side-by-side decisions on transactions over a representative period (typically a few weeks). Tune the new provider's rules and models as needed.
  </Step>

  <Step title="Promote the new provider">
    Flip the flags: set the new provider to **Primary** and the old provider to **Silent** (or **Inactive**). No client-side change is required — the same `anti_fraud_fingerprint` value keeps flowing on every transaction; only enforcement changes.
  </Step>

  <Step title="(Optional) Retire the old provider">
    Once you're confident, set the old provider to **Inactive** to stop traffic to it entirely.
  </Step>
</Steps>

## API reference

Connection mode is set via the [Update anti-fraud service API](/reference/anti-fraud-services/update-anti-fraud-service):

```http theme={"system"}
PUT /anti-fraud-services/{anti_fraud_service_id}
```

```json Request body theme={"system"}
{
  "anti_fraud_service_definition_id": "sift-anti-fraud",
  "active": false,
  "silent": true
}
```

A service cannot be `active` and `silent` at the same time:

* `active: true` makes the service **Primary** (the existing Primary, if any, is automatically deactivated).
* `silent: true` makes it **Silent**.
* If both are `false`, the service is **Inactive**.

`anti_fraud_service_definition_id` is required by the schema, but the underlying provider can't be changed on update — you must echo the service's existing definition string (for example, `sift-anti-fraud`). Read it from the dashboard or from the [Get anti-fraud service](/reference/anti-fraud-services/get-anti-fraud-service) API response for the service you're updating.
