> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Mejores prácticas

> Mejores prácticas de configuración, operación e integración para desplegar y usar el Fees Engine en producción.

Fees Engine te da un control poderoso sobre cómo se calculan, aplican y rastrean las tarifas. Pero con esa flexibilidad viene la necesidad de una configuración cuidadosa y disciplina operacional — especialmente en entornos de producción donde la precisión y la auditabilidad no son negociables.

Estas recomendaciones complementan el [resumen de Fees Engine](/es/midaz/fees/fees-engine-overview) y la guía de [mecánicas de cálculo](/es/midaz/fees/fee-engine-calculation).

## 1. Diseña paquetes de tarifas con nombres claros y segmentación

***

Los paquetes de tarifas son la base de tu lógica de tarifas. Una estructura de paquetes bien organizada facilita el mantenimiento, la depuración y la auditoría de tu configuración de tarifas a lo largo del tiempo.

* **Usa nombres descriptivos** que reflejen el contexto de negocio (ej., "pix-transfer-standard", "wire-premium-segment").
* **Segmenta por producto y grupo de clientes** usando `segmentId`. Esto te permite aplicar diferentes reglas de tarifas a diferentes niveles de clientes sin crear paquetes en conflicto.
* **Mantén los paquetes enfocados**. Un paquete que intenta cubrir demasiados escenarios se vuelve difícil de probar y mantener. Prefiere múltiples paquetes enfocados sobre uno que lo haga todo.
* **Documenta la estructura de tus paquetes** internamente. A medida que la cantidad de paquetes crece, una referencia clara de qué paquete aplica dónde previene errores de configuración.

## 2. Configura las prioridades de tarifas con cuidado

***

Cuando un paquete contiene múltiples tarifas, el campo `priority` determina el orden de ejecución. Equivocarse en esto puede producir cálculos incorrectos.

* **La prioridad 1 siempre debe usar `referenceAmount: originalAmount`**. Esto es aplicado por el motor.
* **Las tarifas con `isDeductibleFrom: true` también deben usar `referenceAmount: originalAmount`**. Esto asegura que las tarifas deducibles siempre se calculen contra el valor total de la transacción.
* **La prioridad debe ser única dentro de un paquete**. Las prioridades duplicadas serán rechazadas.
* **Piensa en las dependencias de tarifas**. Si una tarifa ajusta el valor de la transacción y otra tarifa debe calcularse sobre el valor ajustado, usa `referenceAmount: afterFeesAmount` con un número de prioridad mayor. Si la segunda tarifa debe referir al valor original, usa `originalAmount`.

<Tip>
  En caso de duda, comienza con una configuración simple (una o dos tarifas por paquete) y valida los resultados usando el endpoint de estimación antes de agregar complejidad.
</Tip>

## 3. Siempre estima antes de aplicar tarifas en producción

***

Fees Engine proporciona un [endpoint de estimación](/es/reference/midaz/plugins/fees-engine/simulate-fees) que te permite previsualizar los cálculos de tarifas sin escribir nada en el ledger.

Usa la estimación para:

* **Validar nuevos paquetes** antes de activarlos. Confirma que los valores calculados coincidan con tus resultados esperados en diferentes montos de transacción.
* **Probar casos límite**: transacciones de monto cero, valores límite en los umbrales de `minimumAmount` y `maximumAmount`, y cuentas exentas.
* **Previsualizar tarifas para usuarios**. Si tu producto muestra tarifas antes de la confirmación, usa el endpoint de estimación para proporcionar previsualizaciones precisas.
* **Depurar resultados inesperados**. Si una tarifa calculada no coincide con las expectativas, estima la misma transacción con un `packageId` específico para aislar el problema.

<Note>
  El [endpoint de cálculo](/es/reference/midaz/plugins/fees-engine/calculate-fees) selecciona automáticamente el paquete que mejor coincide. El endpoint de estimación requiere un `packageId` específico, dándote control total sobre qué paquete probar.
</Note>

## 4. Gestiona las exenciones de forma explícita

***

Fees Engine soporta dos tipos de exenciones: por **rango de monto de transacción** y por **cuenta**.

* **Rangos de monto** (`minimumAmount`, `maximumAmount`): Definen la ventana de valor de transacción en la que aplican las tarifas. Las transacciones fuera de este rango están exentas. Usa esto para umbrales promocionales o precios escalonados.
* **Cuentas exentas** (`waivedAccounts`): Cuentas específicas exentas de tarifas dentro de un paquete. Usa esto para cuentas internas, cuentas de empleados o acuerdos de asociación.

Mejores prácticas para exenciones:

* **Mantén las listas de cuentas exentas cortas y revisadas**. Las listas grandes se vuelven difíciles de auditar. Revisa periódicamente qué cuentas están exentas y por qué.
* **Documenta la razón de negocio** de cada exención en tus registros internos.
* **Prueba los límites de exención**. Si tu rango es R$ 0–300, asegúrate de que las transacciones de exactamente R$ 300 y R\$ 301 se comporten como se espera.

## 5. Habilita y ajusta el caché para rendimiento

***

Fees Engine almacena en caché los paquetes de tarifas en memoria para reducir las consultas a la base de datos durante alto tráfico.

Configura el caché mediante variables de entorno:

```yaml theme={null}
fees:
  configmap:
    PACKAGE_CACHE_ENABLED: "true"
    PACKAGE_CACHE_TTL_SECONDS: "600"
```

* **`PACKAGE_CACHE_ENABLED`** (predeterminado: `true`): Habilita o deshabilita el caché de paquetes.
* **`PACKAGE_CACHE_TTL_SECONDS`** (predeterminado: `600`): Tiempo de vida en segundos antes de que los paquetes en caché se actualicen desde la base de datos.

Recomendaciones:

* **Mantén el caché habilitado en producción**. Reduce significativamente la latencia para procesamiento de transacciones de alto volumen.
* **Ajusta el TTL según tu frecuencia de cambios**. Si actualizas paquetes frecuentemente, usa un TTL más corto (ej., 60–120 segundos). Si los paquetes son estables, el valor predeterminado de 600 segundos es apropiado.
* **Ten en cuenta el retraso del caché**. Después de actualizar un paquete, el cambio puede tardar hasta el TTL configurado en propagarse. Si necesitas efecto inmediato, reinicia el servicio o reduce temporalmente el TTL.

## 6. Usa valores numéricos correctos

***

Todos los valores financieros en Fees Engine deben expresarse como **strings** usando el tipo `numeric`. Esto previene errores de precisión de punto flotante que son comunes con aritmética decimal.

```json theme={null}
"value": "12.50"
```

* Siempre envía valores como strings, incluso números enteros (ej., `"100"` no `100`).
* Nunca uses tipos de punto flotante para cálculos monetarios en tu capa de integración.
* Ten en cuenta que las divisiones de tarifas que involucran decimales periódicos (ej., dividir R\$ 10 entre 3 cuentas) se ajustan automáticamente por el motor para mantener los totales del Ledger exactos.

<Warning>
  Fees Engine requiere **Midaz v3.x.x** o posterior. El formato `amount` + `scale` de v2.x.x no es compatible. Actualiza Midaz antes de desplegar Fees Engine.
</Warning>

## 7. Usa soft delete para auditabilidad

***

Cuando eliminas un paquete de tarifas, Fees Engine lo marca con un timestamp `deletedAt` en lugar de eliminarlo de la base de datos. Esto preserva la pista de auditoría para transacciones históricas que referenciaron ese paquete.

* **No dependas del hard delete** para paquetes de tarifas en producción. Las transacciones históricas pueden referenciar paquetes eliminados para conciliación.
* **Revisa periódicamente** los paquetes eliminados si tu base de datos crece significativamente. Las estrategias de archivado pueden ayudar a gestionar el almacenamiento sin perder capacidad de auditoría.

## 8. Monitorea Fees Engine en producción

***

Fees Engine soporta OpenTelemetry para trazas y métricas. Habilítalo para obtener visibilidad del rendimiento y comportamiento de los cálculos de tarifas.

```yaml theme={null}
fees:
  configmap:
    ENABLE_TELEMETRY: "true"
    OTEL_RESOURCE_SERVICE_NAME: "plugin-fees"
```

En producción:

* **Monitorea los endpoints de salud**. Fees Engine expone `/health` para verificaciones de readiness y liveness (puerto predeterminado: 4002).
* **Configura alertas** para latencia alta sostenida en cálculos de tarifas, lo que puede indicar contención en la base de datos o mala configuración del caché.
* **Monitorea MongoDB**: uso del pool de conexiones, espacio en disco y salud de replicación. El valor predeterminado de `MONGO_MAX_POOL_SIZE` es 1000.
* **Revisa el uso de recursos de los pods**. Los límites predeterminados son 200m CPU / 256Mi de memoria. Ajusta según tus patrones de tráfico y comportamiento de autoescalado.

## 9. Mantén las versiones compatibles

***

Antes de actualizar Fees Engine:

* Consulta la [tabla de compatibilidad de versiones](/es/platform/plugins/midaz-version-compatibility) para confirmar compatibilidad con tu versión de Midaz Core.
* Siempre actualiza **Midaz Core primero**, luego Fees Engine.
* Haz respaldo de tus datos de MongoDB y valores de Helm antes de cualquier actualización mayor.
* Prueba la actualización en un entorno de staging antes de aplicarla en producción.

Para procedimientos de actualización, consulta la [guía de actualización de Helm](/es/platform/helm/midaz/midaz-upgrade-guide).

## 10. Revisa las recomendaciones de seguridad

***

Fees Engine procesa datos financieros e integra con operaciones del Ledger de Midaz. Asegúrate de que tu despliegue siga las [Recomendaciones de seguridad](/es/midaz/security-recommendations) de la plataforma, que cubren:

* Segmentación de red y Arquitectura Zero Trust
* Gestión y rotación de secretos (incluyendo `LICENSE_KEY` y credenciales de base de datos)
* Aplicación de TLS 1.2+ para todas las comunicaciones
* Configuración de RBAC vía [Access Manager](/es/platform/access-manager/access-manager)
* Gestión de parches y escaneo de vulnerabilidades

## 11. Diseña billing packages con alcance claro

***

Cada billing package debe representar un cargo único y bien definido. Evita empaquetar precios no relacionados en un solo paquete.

* **Paquetes separados por ruta de transacción**. Un paquete para facturación de Pix y un paquete para facturación de boletos son más claros que un solo paquete que intente manejar ambos.
* **Usa etiquetas descriptivas** que incluyan el tipo de facturación y el objetivo: "Pix Send Monthly Billing — Standard Tier" es mejor que "Billing Package 1".
* **Un tipo de `accountTarget` por paquete de mantenimiento**. No puedes combinar `segmentId`, `portfolioId` y `aliases` en el mismo paquete. Si necesitas diferentes objetivos, crea paquetes separados — una sola llamada a `/billing/calculate` evalúa todos los paquetes activos.

## 12. Elige el modo de conteo correcto

***

El campo `countMode` en paquetes de volumen determina cómo se agrupan las transacciones para el cálculo de precios:

* **`perRoute`** — Cuenta todas las transacciones coincidentes como un total único en toda la organización. Usa esto cuando el precio se aplica al volumen agregado independientemente de qué cuenta generó las transacciones.
* **`perAccount`** — Cuenta transacciones por cuenta individual y aplica niveles de precios de forma independiente. Usa esto cuando cada cuenta de cliente tiene su propio precio basado en volumen.

Una elección incorrecta produce cargos incorrectos. Si tu modelo de precios dice "las primeras 100 transacciones por cliente son gratuitas", usa `perAccount`. Si dice "las primeras 100 transacciones en toda la plataforma son gratuitas", usa `perRoute`.

## 13. Planifica cuotas gratuitas y niveles de descuento con cuidado

***

Las cuotas gratuitas y los descuentos progresivos se evalúan en un orden específico:

1. La cuota gratuita se resta del conteo total primero.
2. Los niveles de precios se aplican al conteo restante.
3. Los niveles de descuento se aplican al monto total resultante.

Consideraciones de diseño:

* **Las cuotas gratuitas se reinician cada período de facturación**. Establece el valor basándote en tu acuerdo comercial por período (mensual o diario), no de por vida.
* **Los niveles de descuento son umbrales acumulativos**, no rangos. Si defines descuentos en 200 y 400 transacciones, un cliente con 500 transacciones obtiene el descuento de 400+ — no ambos.
* **Prueba los límites de tus niveles**. Verifica que la transición entre niveles produzca los resultados esperados, especialmente cuando `freeQuota` empuja el conteo facturable a un nivel inferior al esperado.

<Tip>
  Usa cálculos de prueba con conteos de transacciones conocidos para validar tu configuración de niveles y descuentos antes de habilitar el paquete en producción.
</Tip>

## 14. Dimensiona los objetivos de cuentas de mantenimiento apropiadamente

***

Los paquetes de mantenimiento soportan tres tipos de objetivo con diferentes perfiles de escala:

| Tipo de objetivo | Escala            | Caso de uso                                           |
| ---------------- | ----------------- | ----------------------------------------------------- |
| `segmentId`      | 100,000+ cuentas  | Niveles estándar (PF, PJ, premium)                    |
| `portfolioId`    | Miles de cuentas  | Portfolios empresariales (PME, Corporate, Enterprise) |
| `aliases`        | Hasta 100 cuentas | Cuentas específicas nombradas                         |

Elige el tipo de objetivo que coincida con tu escala operacional. Si te encuentras listando cientos de aliases, migra a un segmento o portfolio en Midaz en su lugar.

## 15. Maneja fallos de facturación con re-ejecución

***

El cálculo de facturación sigue una política de todo-o-nada. Si algún paquete falla, no se devuelven resultados.

* **Construye lógica de reintentos** en tu orquestador. El cálculo no tiene estado — re-ejecutarlo para el mismo período produce los mismos resultados.
* **Revisa las respuestas de error** para identificar el paquete y recurso específico que falló. Causas comunes: `ledgerId` inválido, API de Midaz inaccesible o billing packages deshabilitados.
* **Separa los cálculos de volumen y mantenimiento** si un tipo tiene éxito consistentemente mientras el otro falla. Llama a `/billing/calculate` con `"type": "volume"` y `"type": "maintenance"` de forma independiente para aislar los fallos.
