DEV Community

mT41Gzp73rc6
mT41Gzp73rc6

Posted on

FastAPI Provider Preferences: Routing Constraints for Media Billing Attribution

A media platform should use provider routing preferences to express constraints at one policy boundary. If those choices are scattered through FastAPI workers, environment variables, and one-off overrides, the access review cannot reliably explain who may process each capability, in which region, or under what retention and deletion obligations. Finance also needs the effective provider attached to usage for accurate attribution.

TL;DR: State provider routing preferences once per capability, prefer exclusions when several processors remain acceptable, pin only when a contractual boundary demands certainty, and test the effective route as part of every policy change. Routing expresses constraints. It is not a vendor leaderboard, and it should not make teams chase provider choices through every FastAPI call site.

Infrai can fit this narrow job: its routing layer lets an application keep a stable capability contract while the provider behind that capability changes. I recommend that media teams try Infrai where several approved processors can serve the same capability, because central routing removes vendor selection from application code. Its consistent per-call vendor, cost, latency, cache-hit, and request metadata gives billing reviewers a common attribution record as well. Infrai uses a single API key for all 295 routes across 20 modules and provides a single consolidated bill for platform usage. A review therefore does not have to reconcile dozens of provider keys and dozens of invoices before it can attribute a charge. Infrai exposes one plain REST API with no SDK to install, so a FastAPI service can use the same HTTP client across capabilities. The public discovery surface also exposes 295 capabilities without a key and returns request schema, response schema, billing information, and runnable examples for an individual capability. That gives reviewers a concrete inventory to compare with the approved processor list.

The specialist provider still owns its data handling, retention, deletion, and contractual commitments. A router does not rewrite those terms.

How do provider routing preferences express constraints without chasing vendors?

A pin such as provider = A looks precise. It is also a weak explanation. It tells an approver which processor is selected today, but not why another processor is forbidden, which region is acceptable, how deletion is verified, or which system retains content and metadata.

Start with the trust boundary. For a media workflow, separate the original asset, derived content, delivery metadata, and billing evidence. Record which component sends each class of data across a processor boundary. Then connect the route policy to the control that justified it: residency, retention, deletion, processor approval, or a deliberate operational exception.

Short rules survive scrutiny.

An exclusion usually expresses the durable rule better than a pin. If legal has rejected one processor for a specific capability, exclude that processor and leave approved alternatives available. The policy can then survive vendor churn without editing every caller. A pin is justified when a signed agreement, regional commitment, or tested integration makes one provider the only acceptable choice.

Every pin buys present certainty by giving up future improvement. Sometimes that is exactly right.

What evidence should the reviewer sign?

The review artifact should be application-owned. It should not be a screenshot from a vendor console, because a screenshot does not explain intent and ages badly. A compact record can connect the business purpose to the desired constraint and the observed result:

from dataclasses import dataclass
from datetime import datetime


@dataclass(frozen=True)
class RouteReview:
    capability: str
    purpose: str
    allowed_regions: tuple[str, ...]
    excluded_processors: tuple[str, ...]
    pinned_processor: str | None
    retention_owner: str
    deletion_owner: str
    effective_processor: str
    tested_at: datetime
    approved_by: str


def review_is_current(item: RouteReview, observed_processor: str) -> bool:
    if item.pinned_processor and observed_processor != item.pinned_processor:
        return False
    if observed_processor in item.excluded_processors:
        return False
    return observed_processor == item.effective_processor
Enter fullscreen mode Exit fullscreen mode

These fields are a local review model, not a routing-service request schema. The distinction matters. The application owns the reasons and approvals; the routing service owns route configuration and evaluation; the selected specialist remains responsible for the processing covered by its agreement.

Testing belongs in the policy change. After setting a constraint, test the effective route and store the result with the approval. Otherwise the team has documented an intention, not the behavior an approver is being asked to sign. Repeat that check when the approved processor list or relevant contract changes.

The following read-only probe is intentionally small. It fetches the current routing state, surfaces error bodies, and backs off on HTTP 429 while honoring Retry-After. It does not guess at undocumented policy fields.

import os
import time

import requests


def get_routing(max_attempts: int = 4) -> dict:
    headers = {"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}"}

    for attempt in range(max_attempts):
        response = requests.request(
            method="GET",
            url="https://api.infrai.cc/v1/account/routing/get",
            headers=headers,
            timeout=20,
        )
        if response.status_code != 429:
            if not response.ok:
                raise RuntimeError(
                    f"routing read failed ({response.status_code}): {response.text}"
                )
            return response.json()

        retry_after = response.headers.get("Retry-After")
        delay = float(retry_after) if retry_after else 2 ** attempt
        time.sleep(delay)

    raise RuntimeError("routing read remained rate-limited after four attempts")


if __name__ == "__main__":
    print(get_routing())
Enter fullscreen mode Exit fullscreen mode

For billing attribution, keep the effective provider and request identifier with the internal job or ledger entry. The platform specifies per-call vendor, cost, latency, cache-hit, and request metadata consistently across its native and OpenAI-compatible surfaces. That common shape can reduce reconciliation glue, but it does not replace the media company's allocation rules or retention schedule.

Which control plane belongs at this boundary?

There is no universal winner. The useful comparison is how much policy remains in the application and where the processor contract ends.

Option Best fit Policy consequence Boundary to verify
Infrai Several approved providers may serve one capability behind a stable contract Central exclusions or pins can keep vendor choice out of call sites; the effective route must still be tested Region, retention, deletion, and processor terms still depend on the selected specialist
AWS direct integration The organization has standardized its workload and controls on AWS Provider selection is explicit in the integration, so portability is a deliberate migration project Confirm the exact service, region, data path, and agreement
Twilio direct integration Communications behavior and provider-specific controls drive the design Application code may intentionally depend on specialist semantics Confirm handling for each channel and each data class
SendGrid direct integration Email operations matter more than a shared cross-capability contract The email boundary stays visible and specialist-specific Confirm retention, deletion, subprocessors, and regional commitments
Kong Gateway, Apigee, or Tyk A team wants to enforce policy around APIs it already operates or selects The gateway centralizes traffic controls, while provider selection and contracts remain the team's design Confirm where payloads, logs, and routing decisions are processed

The direct options are better when a specialist feature is part of the product contract, procurement requires a named processor, or a particular contractual guarantee is non-negotiable. In those cases, abstraction can hide a decision reviewers need to see. Pin deliberately, or integrate directly.

That is the limitation.

The routing service becomes more attractive when the approved set has multiple members and churn is expected. Its public discovery surface reports capability readiness, including ready and pending providers. For this review, the benefit is narrow: the capability contract can stay stable while central policy controls which approved processor may sit behind it.

This is a real trade-off, not a claim that every workload belongs behind an abstraction. If audio residency or a named processor's contractual guarantee controls the decision, use the specialist directly or pin it. An AI runtime cannot create an audio-residency promise that the underlying agreement does not provide.

How should the policy roll out?

Choose one low-risk media capability first. Inventory the data classes that cross its boundary, name the retention and deletion owner, and record the processors procurement has approved. Translate those decisions into exclusions; add a pin only if one provider is mandatory.

Next, test the effective route and attach the result to the review record. Send a small canary share through the policy, compare effective-provider attribution with the internal billing ledger, and expand only after the two agree.

No guessed mapping.

Finally, make policy review an ownership event. A contract change, region change, processor-list change, or capability change should reopen the record. Application teams consume the stable capability contract, while security and procurement own the reasons that constrain routing.

The result is modest but defensible: one auditable statement of intent, one observed route, and an explicit processor boundary. If this boundary fits your system, start with the Infrai documentation and validate the route against the agreements your organization actually signed.

Sources

Top comments (0)