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

# Routing logic

> How BlobRouter chooses a provider — priorities, cost formula, assumptions, and fallbacks.

<Info>
  **BlobRouter v0.1** · Last updated: August 2026 · Architecture version: **2.0**
</Info>

BlobRouter’s routing engine is deterministic. No ML. Decisions use live provider pricing (cached in Cloudflare KV) plus explicit assumptions about how a file will be used.

<Note>
  The routing engine makes decisions using configurable assumptions
  (storage duration, request frequency, egress estimates).

  These assumptions are visible and configurable.

  BlobRouter always exposes the assumptions behind every recommendation.
</Note>

## Priority tiers

Pass `priority` on upload:

| Priority  | Meaning                                      | Preferred provider               |
| --------- | -------------------------------------------- | -------------------------------- |
| `hot`     | Frequently read (images, APIs, user content) | Cloudflare R2 (zero egress)      |
| `cold`    | Occasional access                            | Mathematically cheapest provider |
| `archive` | Rarely read (backups, checkpoints)           | Backblaze B2                     |

If you omit `priority`, the API/SDK default is `cold`.

## Cost formula

For each candidate provider we estimate total cost over the assumption window:

```text theme={null}
sizeGb = fileSizeBytes / (1024³)

storageCost  = sizeGb × storagePerGB × monthsStored
egressCost   = sizeGb × readsPerMonth × egressPerGB
requestCost  = (readsPerMonth / 10_000) × requestsPer10k

totalCost    = storageCost + egressCost + requestCost
```

`savedVsAws` is the difference between that total on AWS S3 and the chosen provider (never negative). Pricing rates come from KV (refreshed daily), not hardcoded in the router.

## Default assumptions

These defaults are honest estimates used when you pick a priority. They are returned on routing decisions so you can see exactly what was assumed:

| Priority  | Reads / month | Months stored |
| --------- | ------------- | ------------- |
| `hot`     | 1,000         | 3             |
| `cold`    | 50            | 12            |
| `archive` | 5             | 24            |

Assumptions drive the formula — they are not a guarantee of future traffic. Tune your `priority` to match expected access patterns.

## Preferred provider vs cost formula

1. **Hot** → use R2 if you have R2 credentials; otherwise fall back to cheapest configured provider and set a warning.
2. **Archive** → use B2 if configured; otherwise fall back with a warning.
3. **Cold** → always pick the cheapest configured provider using the formula above.

## When preferred provider is missing

Routing **never fails** solely because R2 or B2 is missing (as long as at least one provider is configured).

Example warning when hot prefers R2 but R2 is not connected:

```text theme={null}
R2 not configured — routed to aws-s3 by cost formula
```

The SDK surfaces this as `routingWarning` (TypeScript) / `routing_warning` (Python) and may emit a console / `warnings.warn` notice.

## EU compliance routing

If you pass `region: "eu"`, BlobRouter checks whether the chosen provider is expected to support EU presence. If residency cannot be guaranteed for the choice, a compliance warning is attached:

```text theme={null}
EU routing unavailable — chosen provider may not meet data residency requirements
```

This does not block the upload in v1 — it warns so you can decide.

## What `routingWarning` means

| Situation          | Typical warning                                                  |
| ------------------ | ---------------------------------------------------------------- |
| Hot without R2     | `R2 not configured — routed to {provider} by cost formula`       |
| Archive without B2 | `B2 not configured — routed to {provider} by cost formula`       |
| EU region concern  | Compliance residency warning (may append to an existing warning) |

Treat warnings as actionable configuration gaps, not hard failures.
