Urgent.News

the world's headlines, one feed

Editions

Tech

Why I Don't Put Tenant-Specific Validation in My FastAPI Endpoints

Multi-tenant applications have a way of turning simple endpoints into surprisingly complicated pieces of code. At first, tenant-specific validation seems harmless. You have two tenants with different limits, so you write something like: if tenant == " acme " : max_quantity = 100 elif tenant == " globex " : max_quantity = 10 It works. The problem isn't the first if . The problem is what happens…

Multi-tenant applications can quickly become complex, with endpoints handling numerous validation rules based on tenant-specific requirements. At first, adding tenant-specific validation might seem harmless, but as more rules are added, the endpoint begins to know too much. Instead of handling the endpoint's primary function – determining what action to take with the request – the route handler takes on the responsibility of resolving tenant information, checking tenant status, determining limits, validating requests, and handling validation failures. This only makes the endpoint harder to understand.

FastAPI's dependency injection offers a natural boundary to separate these concerns. A request header such as X-Tenant-ID can be parsed into a strongly typed TenantConfig, allowing the rest of the request-processing pipeline to access tenant information without repeatedly parsing the header or looking it up. However, some validation rules still require context beyond the request body.

For instance, different tenants might have different maximum order quantities. To handle this, Pydantic v2's validation context can be used. Instead of hard-coding tenant names into the model, the resolved tenant is passed into validation, enabling the validator to access the necessary context through ValidationInfo. The key takeaway here is the separation of responsibilities: FastAPI dependency resolves tenant information, Pydantic validation applies tenant-specific rules, and the endpoint receives a strongly typed TenantOrderContext without needing to know how any of this happens.

There are trade-offs to this approach, though. By manually receiving the request body as raw data and calling model_validate() directly, some FastAPI's automatic request-body handling is lost. This results in a less descriptive OpenAPI documentation. If automatic API documentation is a top priority, a different integration might be more suitable.

Nevertheless, the main goal isn't to eliminate all if statements from an application but to ensure that responsibilities are placed where they make sense. For example, instead of handling all responsibilities within the endpoint, the following code structure is preferable:

def create_order(ctx: TenantOrderContext = Depends(get_validated_order)):

OrderResponse:

This approach keeps the endpoint focused on its primary responsibility – determining the action to take with the request – rather than managing all the validation logic itself. The lesson from this exercise isn't solely about multi-tenancy; it's about understanding where validation information comes from. Some rules depend only on the object being validated, while others rely on the context surrounding it.

When validation depends on external context, placing everything inside the route handler may be easy but isn't necessarily the cleanest solution. FastAPI dependencies and Pydantic v2's validation context provide alternative options for handling this complexity.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — it may contain errors, so check the original before relying on it.

Read the original at dev.to →

More in Tech

Will Apple Be Able to Use CXMT Chips?

The Wall Street Journal reported on Aug. 9 (local time) that Apple is testing memory chips from ChangXin Memory Technologies (CXMT), China’s largest DRAM maker, for use in major product lines such as…

  • Apple testing CXMT memory chips for iPhone and MacBook.
  • CXMT backed by Chinese government, can mass-produce DRAM.
  • U.S. export controls and CXMT's limitations hinder Apple adoption.