MinIO Was Easy, SeaweedFS Made Me Think
A practical SeaweedFS vs MinIO guide for FastAPI apps using boto3, S3-compatible storage, internal and public endpoints, pre-signed URLs, SigV4, Redis caching, and self-hosted media storage.
This is my second product, founded separately from my consumer AI platform. Where the first is a consumer-facing generative AI product, this one is developer infrastructure: a unified layer for integrating, routing, and operating AI models — text, image, video, audio, and speech — behind consistent, provider-independent APIs. The product identity is private, but the architecture and the problem it solves are not.
Teams building on AI models end up integrating multiple providers directly — different auth schemes, different request/response shapes, different failure modes, different billing. Every provider added multiplies integration and operational surface area, and switching or failing over between providers means rewriting application code, not changing a config value.
The bet behind this product is that "which model or provider serves this request" should be an infrastructure decision, not an application one — the same argument that shaped the AI routing layer in my consumer platform, generalized into a standalone product. A unified API means an application developer targets one interface and gets model portability, provider failover, and consistent observability for free.
Every request is authenticated at the edge of the platform, before it reaches routing or provider logic — API keys are scoped per developer/application, which keeps usage metering, billing, and rate limiting attributable and auditable from request one.
The core abstraction normalizes requests and responses across model types — LLMs, image, video, audio, speech-to-text, and text-to-speech — so an application integrates one schema per modality instead of one per provider. Custom and fine-tuned models are exposed through the same interface, so swapping a stock model for a fine-tuned one doesn't require an application-side rewrite.
The routing layer decides which underlying provider or model serves a given request, based on availability, cost, and capability — and can fail over to an alternate provider without the application layer knowing a failover happened. That indirection is the whole point: it turns a hard-coded provider dependency into a configuration concern.
Above simple request routing sits orchestration for multi-step or multi-model workflows — coordinating calls across modalities or providers as a single logical operation, with consistent error handling and retries, rather than leaving that coordination to every application built on top.
Every request is metered at the point of authentication and again at the point of provider usage, so usage-based billing reflects actual consumption rather than estimated or client-reported numbers. This also doubles as the primary reliability signal — metering data is what surfaces provider degradation before it becomes a support ticket.
Billing is derived directly from metered usage rather than maintained as a separate system of record, which avoids the class of bugs where what a customer is billed and what they actually consumed drift apart.
Because the platform sits between applications and third-party inference providers, reliability is partly about the platform itself and partly about how gracefully it handles provider-side failures — timeouts, rate limits, and outages — through retries and failover rather than surfacing every upstream failure directly to the developer.
Request-level observability — latency, error rate, and cost per provider and per model — is treated as a core feature, not an afterthought, since developers routing through a unified layer need visibility into what's actually happening behind the abstraction.
Beyond routing to third-party providers, the platform supports registering custom and fine-tuned models behind the same unified interface — so a team's own model is a routing target like any other, not a separate integration.
The product-level goal throughout has been to make the unified API feel like the obvious default, not a lowest-common-denominator compromise — consistent schemas, predictable errors, and metering/billing that developers can actually reason about.
The hardest part of building unified AI infrastructure isn't any single integration — it's designing an abstraction that stays useful as providers and model types multiply, without leaking every provider's quirks back into the API surface. Getting that abstraction boundary right, so it absorbs provider-specific behavior instead of exposing it, is the recurring design problem behind routing, metering, and billing alike.
A practical SeaweedFS vs MinIO guide for FastAPI apps using boto3, S3-compatible storage, internal and public endpoints, pre-signed URLs, SigV4, Redis caching, and self-hosted media storage.
A practical on-prem Linux deployment guide for FastAPI and Vite apps using Docker Compose, nginx, Postgres, Redis, PM2, no-sudo deployment, health checks, logs, and production runbooks.
How I migrated a FastAPI app from AWS S3 to MinIO using boto3, S3-compatible object storage, pre-signed URLs, SigV4, HTTPS proxying, and a small storage abstraction.