Icono del sitio IT&ライフハックブログ|学びと実践のためのアイデア集

Introducción al diseño orientado a SaaS de planes, facturación y limitación de funciones en FastAPI: patrones prácticos para manejar de forma segura planes gratuitos, planes de pago y estados de suscripción

green snake

Photo by Pixabay on Pexels.com

Introducción al diseño orientado a SaaS de planes, facturación y limitación de funciones en FastAPI: patrones prácticos para manejar de forma segura planes gratuitos, planes de pago y estados de suscripción


Resumen

  • El diseño de planes en SaaS no consiste simplemente en “separar el precio mensual”. Su verdadera esencia es garantizar que toda la aplicación pueda manejar de forma coherente qué contrato permite qué funciones, y hasta qué punto.
  • En FastAPI, más allá de la autenticación, el manejo de tenants y RBAC/ABAC, el diseño se vuelve mucho menos frágil cuando organizas la información del plan, el estado de la suscripción y los límites de uso como dependencias y funciones de política.
  • Lo importante no es decidir solo por plan. En los sistemas reales, debes diseñar en torno a estados de suscripción (active, trialing, past_due, canceled, etc.), add-ons, valores límite, períodos de gracia y cómo deben manejarse los pagos fallidos.
  • Ocultar botones en la UI no es suficiente para limitar funciones. Las decisiones finales siempre deben aplicarse en el backend, y la operación se vuelve mucho más sencilla si esas decisiones también pueden registrarse en audit logs y event logs.
  • Este artículo organiza gradualmente el diseño del modelo de planes en FastAPI, feature flags, límites de uso, manejo de estados de facturación, transiciones de estado basadas en webhooks y estrategias de prueba.

A quién le resultará útil leer esto

Desarrolladores individuales y personas en aprendizaje

Esto es para quienes han empezado a pensar: “Quiero separar un plan gratuito de uno de pago” o “La exportación CSV debería estar disponible solo en planes de pago”.
Al principio, puede que quieras escribir algo sencillo como if user.plan == "pro", pero en cuanto aumentan las funciones, las cosas se vuelven caóticas rápidamente. Este artículo proporciona la base para dar un paso hacia un diseño más organizado.

Ingenieros backend en equipos pequeños

Esto es para equipos que construyen SaaS con FastAPI, donde cada tenant tiene un plan y las restricciones de funciones y límites de uso han ido aumentando gradualmente.
Ayuda a organizar preguntas operativas como “¿En qué capa debemos tomar la decisión?”, “¿Qué debería detenerse durante un fallo de pago?” y “¿Qué debería pasar cuando termina una prueba?” en una forma más fácil de implementar.

Equipos de desarrollo SaaS y startups

Esto es para equipos que enfrentan problemas reales como múltiples planes, add-ons, facturación por uso, períodos de gracia, pagos fallidos y reactivación tras inactividad.
En lugar de centrarse en el propio sistema de facturación, se centra en cómo la aplicación puede reflejar de forma segura el estado de la suscripción, ayudándote a revisar patrones de diseño que sean menos propensos a romperse más adelante.


Nota sobre accesibilidad

  • El artículo muestra primero la visión general y luego avanza en el orden de “terminología”, “modelo de datos”, “límites de funciones”, “estado de facturación”, “webhooks” y “pruebas”, por lo que es fácil de seguir incluso si te incorporas a mitad.
  • Los términos técnicos se explican brevemente cuando aparecen por primera vez, y luego se usan las mismas expresiones de forma consistente para reducir la carga cognitiva.
  • Los ejemplos de código se dividen por pequeñas responsabilidades para que ningún bloque quede sobrecargado.
  • El nivel objetivo es aproximadamente equivalente a AA.

1. El diseño de planes SaaS no es una “tabla de precios”, sino “control de autorización”

Cuando empiezas a construir un SaaS, lo primero que suele hacerse visible es la página de precios.
Es natural querer mostrar un plan Free, un plan Pro y un plan Enterprise, y desde una perspectiva de marketing esa parte destaca mucho.

Sin embargo, la esencia en el lado del backend no es cómo se muestra el precio.
Lo que realmente importa es determinar con seguridad qué puede usar ese tenant en este momento, hasta qué punto y bajo qué estado actual de suscripción.

Por ejemplo, incluso dentro del mismo “plan Pro”, la situación real puede variar así:

  • En prueba
  • Pagado y activo
  • En período de gracia tras un fallo de pago
  • Programado para cancelación
  • Configurado para detenerse al final de este mes
  • Con capacidad extra comprada solo mediante add-ons

Dada esa realidad, una comprobación simple como plan == "pro" no es suficiente.
Por eso, el centro del diseño necesita información como:

  • Tipo de plan
  • Estado de suscripción
  • Fecha de expiración
  • Límites de uso
  • Add-ons
  • Excepciones temporales o contratos especiales

Este artículo examina cómo mapear todo este panorama en dependencias y políticas de FastAPI.


2. Términos que conviene organizar primero: plan, suscripción, estado de suscripción y función

Para evitar mezclar conceptos, organicemos primero la terminología.

Plan

Un plan es un concepto cercano al “nombre de producto” del conjunto de funciones ofrecidas.

Ejemplos:

  • free
  • starter
  • pro
  • enterprise

Un plan es relativamente estático y es la categoría que también aparece en la página de precios.

Subscription

Una suscripción es el registro contractual real que representa en qué plan está actualmente un tenant.
No es el plan en sí, sino un registro que contiene el estado contractual activo.

Subscription state

El estado de suscripción indica la facturación, la validez y la condición de detención.

Ejemplos:

  • trialing
  • active
  • past_due
  • canceled
  • paused
  • expired

En el trabajo real, si una función puede usarse o no a veces está influido más fuertemente por el estado de suscripción que por el nombre del plan.

Feature

Una feature es una capacidad que una persona usuaria puede usar realmente dentro de la aplicación.

Ejemplos:

  • Crear proyectos
  • Exportación CSV
  • Acceso API
  • Configuración de webhooks
  • Ver audit logs
  • Límites de capacidad de almacenamiento
  • Límites de número de miembros

Cómo representar estas “features” es el núcleo del diseño del lado de la aplicación.


3. La política de diseño que deberías decidir primero: evita hardcodear nombres de planes

Una implementación común al principio se parece a esto:

if tenant.plan == "pro":
    # CSV export allowed

Al principio, esto es muy fácil de entender.
Pero al poco tiempo aparecen rápidamente los siguientes problemas.

  • Puede que quieras habilitar CSV también para starter
  • Enterprise puede necesitar audit logs además de CSV
  • Algunos clientes pueden necesitar CSV como excepción especial
  • Puede que quieras desbloquear solo algunas funciones durante la prueba
  • Durante un fallo de pago, puede que quieras detener solo CSV

Entonces if tenant.plan in {...} empieza a extenderse por todas partes, y después resulta imposible seguirlo correctamente.

Así que desde el principio recomiendo la siguiente política:

  1. Trata los nombres de los planes como etiquetas de producto
  2. Realiza las comprobaciones reales de funciones usando “feature keys”
  3. Gestiona los límites de uso por separado como valores numéricos
  4. Trata el estado de suscripción de forma independiente del plan

Con esta estructura, incluso si reorganizas los planes más adelante, se necesitarán menos cambios en el lado de la aplicación.


4. Modelo de datos básico: separa Tenant, Subscription y PlanFeature

Primero creemos un modelo conceptual mínimo.

4.1 Tenant

Un tenant es la propia organización cliente.

# app/models/tenant.py
from pydantic import BaseModel

class Tenant(BaseModel):
    id: int
    name: str
    is_active: bool = True

4.2 Subscription

El contrato real debería almacenarse por separado.

# app/models/subscription.py
from pydantic import BaseModel
from typing import Literal
from datetime import datetime

PlanCode = Literal["free", "starter", "pro", "enterprise"]
SubscriptionStatus = Literal[
    "trialing",
    "active",
    "past_due",
    "paused",
    "canceled",
    "expired",
]

class Subscription(BaseModel):
    tenant_id: int
    plan_code: PlanCode
    status: SubscriptionStatus
    current_period_end: datetime | None = None
    cancel_at_period_end: bool = False
    trial_ends_at: datetime | None = None

4.3 Plan features

La relación entre planes y funciones debería mantenerse en una tabla o configuración separada.

# app/models/plan_feature.py
from pydantic import BaseModel

class PlanFeature(BaseModel):
    plan_code: str
    feature_key: str
    enabled: bool = True
    limit_value: int | None = None

Si lo estructuras así, incluso cuando quieras añadir una nueva función al plan pro, solo necesitas actualizar la relación entre el plan y la función.


5. Define primero las feature keys: fija nombres orientados a máquina antes que nombres orientados a personas

Si vas a implementar restricciones de funciones, primero necesitas una forma legible por máquina de expresar qué es exactamente lo que se está restringiendo.

Por ejemplo, claves como estas:

  • project.create
  • project.export_csv
  • audit_log.view
  • api.access
  • webhook.create
  • member.max_count
  • storage.max_bytes

Lo importante aquí es separar las funciones de tipo booleano de las funciones basadas en límites.

Boolean features

  • Se puede usar / no se puede usar

Ejemplos:

  • audit_log.view
  • project.export_csv

Limit-based features

  • Hasta cuántos, cuántas personas, cuántos GB

Ejemplos:

  • member.max_count = 5
  • storage.max_bytes = 1073741824

Sin esta distinción, el diseño se vuelve muy difícil de gestionar más adelante.


6. Política básica en FastAPI: obtén la información de la suscripción mediante dependencias

En FastAPI, al igual que con usuarios autenticados e información del tenant, es más fácil mantener las cosas organizadas si obtienes la suscripción actual a través de una dependencia.

6.1 Obtener el tenant actual

Asumamos, en línea con artículos anteriores, que el ID del tenant actual ya está resuelto.

# app/deps/tenant.py
def get_current_tenant_id() -> int:
    return 10

6.2 Obtener la suscripción actual

# app/deps/subscription.py
from fastapi import Depends, HTTPException, status
from app.deps.tenant import get_current_tenant_id
from app.models.subscription import Subscription

def get_current_subscription(
    tenant_id: int = Depends(get_current_tenant_id),
) -> Subscription:
    # In reality, fetch from DB or cache
    if tenant_id == 10:
        return Subscription(
            tenant_id=10,
            plan_code="pro",
            status="active",
        )

    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail="subscription not found",
    )

Con esto, cada router y cada service layer puede referirse de forma consistente a “la información de suscripción del tenant actual”.


7. Convierte las comprobaciones de funciones en funciones: has_feature() y get_limit()

Para evitar dispersar nombres de planes por toda la app, prepara funciones de comprobación de funciones.

# app/services/plan_service.py
from app.models.subscription import Subscription

FEATURE_MATRIX = {
    "free": {
        "project.export_csv": False,
        "audit_log.view": False,
        "api.access": False,
        "member.max_count": 3,
        "storage.max_bytes": 100 * 1024 * 1024,
    },
    "pro": {
        "project.export_csv": True,
        "audit_log.view": True,
        "api.access": True,
        "member.max_count": 20,
        "storage.max_bytes": 5 * 1024 * 1024 * 1024,
    },
    "enterprise": {
        "project.export_csv": True,
        "audit_log.view": True,
        "api.access": True,
        "member.max_count": 9999,
        "storage.max_bytes": 100 * 1024 * 1024 * 1024,
    },
}
# app/services/plan_service.py (continued)
def has_feature(subscription: Subscription, feature_key: str) -> bool:
    plan_features = FEATURE_MATRIX.get(subscription.plan_code, {})
    value = plan_features.get(feature_key, False)
    return bool(value) if isinstance(value, bool) else True

def get_limit(subscription: Subscription, feature_key: str) -> int | None:
    plan_features = FEATURE_MATRIX.get(subscription.plan_code, {})
    value = plan_features.get(feature_key)
    return value if isinstance(value, int) else None

Esta implementación es solo un ejemplo mínimo, pero el punto importante es centralizar la lógica de decisión en un solo lugar.


8. Incluye siempre el estado de suscripción en la decisión: no asumas que solo active significa usable

Una omisión común en las comprobaciones de planes es el estado de suscripción.
Por ejemplo, incluso con un plan pro, si el estado es past_due, puede que necesites distinguir entre “funciones que pueden seguir usándose” y “funciones que deberían detenerse”.

Así que en lugar de mirar solo has_feature(), también deberías comprobar si la suscripción está en un estado utilizable.

# app/services/subscription_policy.py
from app.models.subscription import Subscription

ACTIVE_LIKE = {"trialing", "active"}

def is_subscription_usable(subscription: Subscription) -> bool:
    return subscription.status in ACTIVE_LIKE

Sin embargo, en la práctica, past_due a menudo no se corta de inmediato.
Por ejemplo, puede haber un período de gracia de 3 días después de un fallo de pago durante el cual se permite acceso de solo lectura, mientras que las operaciones de escritura se detienen.

Por eso es útil dividir los juicios de estado por tipo de operación, así:

# app/services/subscription_policy.py
def can_use_read_features(subscription: Subscription) -> bool:
    return subscription.status in {"trialing", "active", "past_due"}

def can_use_write_features(subscription: Subscription) -> bool:
    return subscription.status in {"trialing", "active"}

def can_use_export_features(subscription: Subscription) -> bool:
    return subscription.status in {"active"}

Esta estructura te permite cambiar el comportamiento con flexibilidad durante un fallo de pago.


9. Expresa “feature requerida” mediante dependencias

De una manera más propia de FastAPI, usar dependencias para funciones requeridas hace que la intención del router sea más fácil de leer.

9.1 Restricción para una función tipo feature-flag

# app/deps/plan_permissions.py
from fastapi import Depends, HTTPException, status
from app.deps.subscription import get_current_subscription
from app.services.plan_service import has_feature
from app.services.subscription_policy import can_use_write_features

def require_csv_export_feature(
    subscription = Depends(get_current_subscription),
):
    if not can_use_write_features(subscription):
        raise HTTPException(
            status_code=status.HTTP_402_PAYMENT_REQUIRED,
            detail="subscription is not usable for export",
        )

    if not has_feature(subscription, "project.export_csv"):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="csv export is not available for this plan",
        )

    return subscription

9.2 Usarlo en el router

# app/api/v1/routers/projects.py
from fastapi import APIRouter, Depends
from app.deps.plan_permissions import require_csv_export_feature

router = APIRouter(prefix="/projects", tags=["projects"])

@router.get("/export")
def export_projects_csv(
    subscription = Depends(require_csv_export_feature),
):
    return {"status": "export started", "plan": subscription.plan_code}

Ahora, la intención de que “la exportación CSV tiene condiciones de plan” puede leerse directamente desde el router.


10. Restricciones basadas en límites: manejar de forma segura recuentos, capacidad y límites de asientos

No solo son importantes las funciones de tipo booleano, sino también los límites de cantidad y capacidad en SaaS.

10.1 Ejemplo: límite de número de miembros

Si quieres que “free permita hasta 3 personas” y “pro permita hasta 20 personas”, deberías comprobar el límite antes de añadir.

# app/services/member_policy.py
from app.models.subscription import Subscription
from app.services.plan_service import get_limit

def can_add_member(subscription: Subscription, current_member_count: int) -> bool:
    limit = get_limit(subscription, "member.max_count")
    if limit is None:
        return True
    return current_member_count < limit

10.2 Usarlo en la service layer

# app/services/member_service.py
from fastapi import HTTPException, status
from app.models.subscription import Subscription
from app.services.member_policy import can_add_member

def invite_member(subscription: Subscription, current_member_count: int):
    if not can_add_member(subscription, current_member_count):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="member limit reached",
        )
    return {"status": "invited"}

10.3 Ejemplo: límites de capacidad de almacenamiento

Esto también encaja bien con el diseño de subida de archivos, pero aquí se aplica la misma lógica a los límites de almacenamiento.

  • Agregar el uso actual total
  • Sumar el tamaño esperado de la nueva subida
  • Rechazar si supera storage.max_bytes

Si colocas esa comprobación en la service layer de upload, puedes mantener la coherencia con el plan.


11. Diseño de add-ons: prepararse para la realidad que no puede expresarse solo con planes

En productos SaaS reales, son comunes “compras adicionales” como las siguientes:

  • Paquete extra de miembros
  • Almacenamiento adicional
  • Retención extendida de audit logs
  • Cuota adicional de acceso API
  • Slots extra de webhook

En estos casos, los planes por sí solos no son suficientes.
Por eso resulta útil un diseño que incluya addons además de subscription.

# app/models/addon.py
from pydantic import BaseModel

class Addon(BaseModel):
    tenant_id: int
    addon_key: str
    quantity: int = 1

Por ejemplo, podrías calcular el storage.max_bytes final así:

  • Valor base del plan
  • Valor añadido por add-ons
  • Override de campañas o contratos especiales

Si centralizas esto en una función como effective_limit(), será mucho más fácil cambiarlo más adelante.


12. Diseño de trial: pensarlo desde el principio hace las cosas más fáciles después

Los trials también afectan a los ingresos, así que vale la pena organizarlos desde el principio.

Políticas comunes

  • Durante el trial, desbloquear parte o todas las funciones equivalentes a pro
  • Una vez que trial_ends_at ha pasado, pasar a expired o a un estado equivalente a free
  • Decidir claramente si la facturación comienza automáticamente tras el trial o si espera a un upgrade manual

Lo importante en la práctica es no crear una lógica separada para juzgar el trial y otra distinta para juzgar el plan normal.
Un patrón recomendado es tratar el trial como una suscripción normal con status="trialing" y absorber el comportamiento dentro de las funciones de decisión.


13. Transiciones de estado basadas en webhooks: cómo reflejar eventos de facturación dentro de la app

En SaaS, el estado de suscripción suele cambiar mediante webhooks procedentes de sistemas de pago o facturación.
El punto importante aquí es separar responsabilidades para que, “cuando llega un evento externo, la app actualice su estado interno de Subscription”.

13.1 Eventos típicos

  • Suscripción creada
  • Trial iniciado
  • Renovación exitosa
  • Pago fallido
  • Pago confirmado
  • Cancelación programada
  • Cancelación inmediata
  • Cambio de plan

13.2 Mantener el estado como “source of truth” dentro de la app

En lugar de consultar el servicio externo en tiempo real cada vez, es más estable mantener el estado actual de Subscription dentro de la aplicación.

Las razones incluyen:

  • Las respuestas API se vuelven más rápidas
  • Las decisiones siguen funcionando durante caídas temporales del sistema externo
  • Es más fácil de probar
  • Es más fácil conectar cambios de estado con audit logs

Así que el manejo de webhooks debería seguir un flujo como este:

  1. Recibir el evento
  2. Verificar su legitimidad
  3. Actualizar Subscription
  4. Emitir audit logs o domain events si es necesario

14. Diseño UX durante un fallo de pago: ¿detener todo o detener por etapas?

El fallo de pago afecta tanto a la experiencia del producto como a los ingresos.
Si esta parte es ambigua, la operación se vuelve muy confusa.

Control por etapas habitual

  • Inmediatamente después de pasar a past_due
    • Lectura permitida, escritura bloqueada
  • Tras finalizar el período de gracia
    • Login permitido, funciones principales bloqueadas
  • Suspensión total
    • Todo fuertemente restringido excepto la pantalla de gestión de suscripción

Para reflejar esto en FastAPI, es más fácil dividir la granularidad de decisión como se mostró antes:

  • can_use_read_features
  • can_use_write_features
  • can_use_export_features

Esa estructura es mucho más fácil de manejar.


15. Integración con audit logs: registra siempre los cambios de facturación y de plan

Esto también se conecta con el contexto del artículo anterior, pero los cambios relacionados con planes y facturación son objetivos extremadamente importantes para audit logs.

Ejemplos de eventos que querrás registrar:

  • subscription.created
  • subscription.plan_changed
  • subscription.past_due
  • subscription.canceled
  • subscription.reactivated
  • addon.added
  • addon.removed

Estos eventos son útiles tanto para atención al cliente como para investigación de incidentes.
Para explicar “¿Por qué ayer estaba disponible la exportación CSV y hoy no?”, necesitas el historial del estado de suscripción.


16. Combinar con RBAC/ABAC: trata las restricciones del plan como parte de la autorización

La conexión importante con el artículo anterior sobre RBAC/ABAC es que las restricciones del plan también deberían tratarse como parte de la autorización.

Por ejemplo, que la exportación CSV esté permitida puede ser el resultado de las siguientes condiciones acumuladas:

  • RBAC
    • viewer no está permitido
  • ABAC
    • Debe pertenecer al mismo tenant
  • Subscription state
    • Debe ser active
  • Plan feature
    • project.export_csv debe estar habilitada

Así que la autorización final se convierte en una composición como esta:

Authenticated
AND belongs to tenant
AND required role
AND required attribute conditions
AND subscription state OK
AND plan feature OK

Pensar en este orden hace que sea sorprendentemente fácil de organizar aunque parezca complejo.


17. Patrones comunes de fallo

17.1 tenant.plan == "pro" está disperso por todo el código

Más adelante ya no podrás manejar con seguridad cambios de plan o contratos excepcionales.
Muévelo siempre a funciones o políticas.

17.2 No comprobar el estado de suscripción

Incluso un contrato pro puede estar en past_due o canceled.
Necesitas tratar plan_code y status por separado.

17.3 Restringir solo en la UI sin proteger el backend

Ocultar un botón no significa nada si la API puede seguir siendo llamada.
La decisión final siempre debe aplicarse en el lado de FastAPI.

17.4 Hardcodear valores límite como constantes

Si “hasta 5” y “hasta 10” están dispersos por ahí, los cambios de plan crearán accidentes.
Centralízalos en funciones como get_limit().

17.5 Usar eventos de webhook directamente para decisiones de negocio

Si dependes solo del estado inmediato en el momento en que llega el evento externo, el diseño se vuelve inestable.
Es más seguro almacenar un estado normalizado de Subscription dentro de la aplicación.


18. Estrategia de pruebas: las limitaciones de planes se rompen más fácilmente de lo que parece

La combinación de planes y estados de facturación es más frágil de lo que parece.
Por eso es mejor protegerla con tests unitarios y tests de API.

18.1 Tests mínimos que deberías tener

  • free no puede exportar CSV
  • pro puede exportar CSV
  • Incluso pro no puede exportar mientras esté en past_due
  • free no puede añadir miembros después de alcanzar el límite
  • Enterprise puede ver audit logs
  • La cancelación programada sigue permitiendo el uso durante el período activo
  • El comportamiento tras terminar el trial es exactamente el previsto

18.2 Ejemplo de test unitario

# tests/test_plan_service.py
from app.models.subscription import Subscription
from app.services.plan_service import has_feature, get_limit

def test_pro_has_csv_export():
    subscription = Subscription(tenant_id=10, plan_code="pro", status="active")
    assert has_feature(subscription, "project.export_csv") is True

def test_free_member_limit():
    subscription = Subscription(tenant_id=10, plan_code="free", status="active")
    assert get_limit(subscription, "member.max_count") == 3

18.3 Ejemplo de test de estado de suscripción

# tests/test_subscription_policy.py
from app.models.subscription import Subscription
from app.services.subscription_policy import can_use_export_features

def test_past_due_cannot_export():
    subscription = Subscription(tenant_id=10, plan_code="pro", status="past_due")
    assert can_use_export_features(subscription) is False

Si mantienes estos tests de funciones puras con una cobertura razonable, las revisiones de planes se vuelven mucho más seguras.


19. Hoja de ruta según el tipo de lector

Para desarrolladores individuales y personas en aprendizaje

  1. Empieza solo con free y pro
  2. Evita hardcodear tenant.plan y crea has_feature()
  3. Maneja al menos un valor límite, como el número de miembros, mediante get_limit()
  4. Añade restricciones tipo 403 o 402 a las APIs principales

Para ingenieros en equipos pequeños

  1. Crea una “lista de funciones” antes que una tabla de precios
  2. Separa el modelo en plan_code, status y limit
  3. Usa dependencias para obtener la información de suscripción actual
  4. Mueve las comprobaciones inline de los routers a funciones de política
  5. Registra eventos de cambio de suscripción en audit logs

Para equipos SaaS y startups

  1. Organiza las responsabilidades entre planes, add-ons y estados de facturación
  2. Sincroniza el estado de Subscription mediante webhooks
  3. Documenta explícitamente períodos de gracia y políticas de suspensión
  4. Integra las restricciones del plan en la misma capa de autorización que RBAC/ABAC
  5. Refleja también estas restricciones en OpenAPI, pantallas de administración y procedimientos de atención al cliente

Referencias


Conclusión

  • El diseño de planes orientado a SaaS no es solo una tabla de precios, sino el diseño de autorización, gestión de límites y gestión de estados en toda la aplicación.
  • En FastAPI, el diseño se vuelve mucho más estable si obtienes la información de suscripción actual mediante dependencias y centralizas las comprobaciones de funciones y límites en funciones de política.
  • Trata plan_code y status por separado, y si es necesario permite añadir add-ons y contratos excepcionales por encima. Eso hace que el diseño sea mucho más sólido ante cambios futuros.
  • Es importante no solo controlar la visualización en la UI, sino también aplicar las restricciones de funciones en el backend y protegerlas mediante audit logs y pruebas.
  • No necesitas construir una base de facturación perfecta desde el primer día, pero si separas desde el inicio “feature keys”, “limits” y “subscription states”, el sistema se vuelve mucho más resistente a medida que crece.

Un siguiente artículo natural en este flujo sería algo como “patrones de diseño en FastAPI para APIs internas de paneles de administración” o “implementación segura de APIs receptoras de webhooks”.

Salir de la versión móvil