Documentación
Límites del plan
Aplicación server-side de límites del plan con el catálogo de billing y checkLimit().
Motoko Base define límites numéricos del plan en src/lib/billing/config/plans.ts (PLAN_CATALOG). La página de ajustes de Usage muestra el progreso respecto a esos límites. La aplicación ocurre en el servidor en las mutaciones de features — nunca solo en la UI.
Architecture
PLAN_CATALOG.limits
↓
getBillingSummary(userId) → summaryGetLimit()
↓
checkLimit(userId, limitId, currentUsage, delta)
↓
Server Action / route handler rejects or allows mutationLos límites se resuelven a partir del resumen de billing del usuario. Los usuarios sin acceso de pago (incluido past_due) reciben límites del plan Free. Cuando Polar no está configurado, checkLimit() permite las mutaciones para que el desarrollo local con configuración mínima siga funcionando.
checkLimit API
import { checkLimit } from "@/lib/billing";
const result = await checkLimit(userId, "links", currentCount, 1);
if (result.status === "limit_reached") {
// reject mutation with user-facing message
}
if (result.status === "unavailable") {
// billing lookup failed — fail closed with safe error
}Resultados:
| Status | Meaning |
|---|---|
allowed | La mutación puede continuar (limit: null = ilimitado) |
limit_reached | Excedería el límite del plan |
unavailable | No se pudo resolver el resumen de billing |
Shipped enforcement
| Feature | Boundary | Notes |
|---|---|---|
| Links | createLinkAction | Update/delete no se bloquean por el límite |
| Storage | createUploadAction + confirmUploadAction | Pre-verificación al iniciar; verificación definitiva al confirmar (ciclo de vida de subida presignada) |
El uso de storage cuenta filas files con status = "ready", sumando sizeBytes. Las subidas pendientes solo se incluyen en la pre-verificación de init.
Usage metrics registry
La visualización de uso (src/lib/billing/usage.ts) lee métricas de un registro. Cada feature registra su medida:
// src/features/links/usage-metric.ts
registerUsageMetric({
id: "links",
limitId: "links",
label: "Links",
measure: countLinksForUser,
});Importa @/features/dashboard/lib/bootstrap-usage-metrics (o los módulos individuales usage-metric.ts) antes de llamar a getUsageSnapshot() para que las métricas estén registradas.
Eliminar un demo: borra la carpeta del feature y su usage-metric.ts. No hace falta editar src/lib/billing/usage.ts.
Adding limits to a new feature
- Añade un
LimitIdy un valor de límite aPLAN_CATALOGenconfig/plans.ts. - Exporta una función
measure(userId)desde las queries de tu feature. - Registra la métrica en
<feature>/usage-metric.ts. - Llama a
checkLimit()en la mutación del servidor antes de persistir el nuevo estado que consume cuota. - Pasa el uso
currentcomo parámetro — no codifiques límites del plan en el feature.
Concurrency
Links y storage usan aplicación best-effort: dos creaciones concurrentes cerca del límite pueden tener éxito brevemente. Esto es aceptable para el starter y está documentado con honestidad. Una aplicación estricta requeriría transacciones o bloqueos por usuario — añádelo en tu producto si necesitas garantías fuertes.
Las subidas concurrentes de storage siguen el mismo modelo: la verificación definitiva se ejecuta en confirm/finalización, pero dos confirmaciones cerca del límite pueden pasar ambas en condiciones de carrera.
Related docs
- Payments (Polar) — resumen de billing y entitlements
- Storage — ciclo de vida de subida
src/lib/security/README.md— valores por defecto de seguridad