# Rate Limiting and Authentication for Production Deployment in Hugging Face Speech-to-Speech

> Secure your Hugging Face Speech-to-Speech deployment with built-in stateless authentication and tier-based rate limiting. Protect your service and manage usage effectively.

- Repository: [Hugging Face/speech-to-speech](https://github.com/huggingface/speech-to-speech)
- Tags: best-practices
- Published: 2026-08-03

---

**The speech-to-speech repository provides stateless authentication and tier-based rate limiting through [`demo/auth.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/auth.py) and [`demo/limiter.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/limiter.py), automatically activating when deployed as a Hugging Face Space to enforce daily talk-time budgets without external databases.**

The `huggingface/speech-to-speech` demo is designed for production deployment on Hugging Face Spaces, where protecting compute resources from abuse is critical. The codebase implements a dual-layer protection system that handles user identification through OAuth and token validation while enforcing daily usage caps based on user tiers. Rate limiting and authentication for production deployment are handled entirely within the FastAPI application layer, requiring only environment variables and Space secrets to configure.

## Architecture Overview

The production protection stack consists of two independent subsystems wired into the FastAPI server in [`demo/server.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/server.py):

- **[`demo/auth.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/auth.py)** – Handles OAuth flows, token extraction, and user tier resolution via functions like `attach()`, `current_access_token()`, and `resolve_identity()`.
- **[`demo/limiter.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/limiter.py)** – Manages daily talk-time budgets through `budget_for()` and per-session bookkeeping logic.

When the server starts, it detects whether it is running inside a Hugging Face Space by checking for the presence of `SPACE_ID` and `LOAD_BALANCER_URL`. If both are present, the limiter and auth subsystems are enabled:

```python

# demo/server.py

LIMITER_ENABLED = bool(LOAD_BALANCER_URL) and bool(SPACE_ID)
AUTH_ENABLED = LIMITER_ENABLED and auth.attach(app)

```

## Authentication Flow

The authentication system is deliberately stateless, relying on JWT tokens and in-memory caching rather than persistent user databases.

### OAuth Activation

If the environment variable `HF_OAUTH` is set to `"true"`, the `auth.attach(app)` function registers Hugging Face OAuth endpoints by calling `huggingface_hub.attach_huggingface_oauth(app)`. This adds the `/oauth/huggingface/*` routes to the FastAPI application, allowing users to authenticate via their Hugging Face accounts.

### Token Extraction and Identity Resolution

For every incoming request, the system extracts and validates credentials through a three-step process:

1. **Token extraction** – `current_access_token(request)` reads the `Authorization` header or the OAuth cookie set by the login flow, returning a stripped token string or `None`.
2. **Identity resolution** – `resolve_identity(request)` uses the token to look up the user's tier, API keys, and any "unlimited-org" status. It returns a tuple of `(tier, keys, set_cookie_flag)`.
3. **User view** – `user_view(request)` constructs a JSON response sent to the client containing UI hints such as `auth`, `tier`, and `loginUrl`.

## Rate Limiting Implementation

The rate limiter prevents resource exhaustion by tracking talk-time consumption against daily quotas defined per user tier.

### Tier-Based Budgets

The `budget_for(tier)` function in [`demo/limiter.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/limiter.py) returns the daily second-budget for the given tier as an integer, or `None` for unlimited access. Budget mappings are loaded from the `S2S_BUDGETS` Space secret (JSON format) and fall back to a temporary file under `/tmp` if the secret is unavailable.

### Session Accounting

When a new realtime session is created, the server initializes a SQLite database (stored under `/data`) to track remaining allowance for that specific session. Every 5 seconds, the server reports a **budget chunk** (`CHUNK_SEC`) that the client may consume. The limiter subtracts used time from the stored budget and returns `False` once the daily quota is exhausted, prompting the client to terminate the session.

The limiter employs **conservative accounting**: it uses the maximum of "seconds spent on the current session identifier" and "seconds spent on the same user key" to prevent users from resetting their budget by opening new sessions.

## Deploy-Time Configuration

Configure these environment variables to activate production protection:

| Variable | Purpose | Example Value |
|----------|---------|---------------|
| `HF_SPACE_ID` | Space identifier (set automatically on Hugging Face) | `username/space-name` |
| `LOAD_BALANCER_URL` | External load balancer URL required for rate limiting | `https://lb.huggingface.co` |
| `HF_OAUTH` | Enable OAuth flow | `true` |
| `S2S_BUDGETS` | JSON mapping of tier to daily seconds | `{"anonymous": 300, "signed_in": 1800, "pro": null}` |
| `UNLIMITED_ORGS` | Comma-separated organization IDs with unlimited budget | `org-abc,org-xyz` |

## Implementation Examples

### Enabling Protection in Custom Deployments

To manually enable authentication and rate limiting outside of Hugging Face Spaces:

```python
from fastapi import FastAPI
from demo import auth, limiter
import os

app = FastAPI()

if bool(os.getenv("LOAD_BALANCER_URL")) and bool(os.getenv("HF_SPACE_ID")):
    auth.attach(app)          # Registers OAuth routes & token parsing

    limiter_enabled = True   # Signal to server routes

else:
    limiter_enabled = False

```

### Resolving User Identity in Endpoints

Extract the user's tier and API keys within any route:

```python
from fastapi import Request, APIRouter
from demo import auth

router = APIRouter()

@router.get("/whoami")
def whoami(request: Request):
    tier, keys, _ = auth.resolve_identity(request)
    return {"tier": tier, "api_keys": keys}

```

### Checking Remaining Budget

Validate whether a user has talk-time remaining before processing:

```python
from demo import limiter

def is_allowed(tier: str) -> bool:
    # Returns True if daily budget is not exhausted

    remaining = limiter.budget_for(tier)
    return remaining is None or remaining > 0

```

### Client-Side Authentication

Connect to the API using personal access tokens:

```python
import httpx

token = "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
headers = {"Authorization": f"Bearer {token}"}

async with httpx.AsyncClient() as client:
    resp = await client.post(
        "https://my-space.hf.space/api/session", 
        headers=headers
    )
    # Server resolves token → tier → budget automatically

```

## Summary

- **Authentication** is handled statelessly in [`demo/auth.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/auth.py) via OAuth and Bearer tokens, requiring no external database.
- **Rate limiting** tracks daily talk-time budgets per tier in [`demo/limiter.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/limiter.py), using SQLite for per-session bookkeeping under `/data`.
- **Automatic activation** occurs when `LOAD_BALANCER_URL` and `HF_SPACE_ID` are present, making the system ideal for serverless Space deployments.
- **Conservative accounting** prevents budget circumvention by tracking both session identifiers and user keys.
- **Configuration** relies entirely on environment variables and Space secrets (`S2S_BUDGETS`, `UNLIMITED_ORGS`).

## Frequently Asked Questions

### How does the server detect it is running in a Hugging Face Space?

The server checks for the presence of both `SPACE_ID` and `LOAD_BALANCER_URL` environment variables at startup in [`demo/server.py`](https://github.com/huggingface/speech-to-speech/blob/main/demo/server.py). When both are present, it sets `LIMITER_ENABLED = True` and attempts to attach the authentication handlers.

### What happens when a user exhausts their daily budget?

Once the `budget_for()` function returns a value of zero or the per-session SQLite tracker reaches zero, the limiter returns `False` to the server. The server then signals the client to shut down the session, terminating the connection until the next daily reset.

### Can organizations bypass rate limiting entirely?

Yes. Organization IDs listed in the `UNLIMITED_ORGS` environment variable receive a `None` response from `budget_for()`, causing the limiter to skip all accounting. Similarly, tiers mapped to `null` in the `S2S_BUDGETS` JSON configuration receive unlimited access.

### Is a database required to store user sessions or budgets?

The authentication system is completely stateless and requires no database. However, the rate limiter uses a lightweight SQLite database stored under `/data` strictly for per-session bookkeeping of remaining talk-time, not for storing user profiles or credentials.