El problema: la lógica duplicada
Es habitual que, para avanzar rápido, la web y la app calculen cada una ciertas cosas por su cuenta: el total de un carrito, si un usuario puede acceder a una función o qué estado mostrar de un pedido. Con el tiempo, una cambia y la otra no, y los usuarios ven resultados distintos según el canal.
El principio que lo evita es sencillo: las reglas de negocio viven en el backend. Las aplicaciones muestran información y capturan acciones, pero no deciden precios, permisos ni estados.
Las apps móviles no se actualizan cuando tú quieres
Una web se actualiza para todos cuando publicas. Una app móvil, no: siempre habrá usuarios con versiones antiguas durante semanas o meses. Esto tiene consecuencias directas en el diseño de la API:
- Compatibilidad hacia atrás: no elimines ni cambies el significado de campos que usan versiones publicadas. Agrega campos nuevos y deja de usar los viejos de forma gradual.
- Versionado explícito: cuando un cambio incompatible sea inevitable, publícalo como una nueva versión del endpoint y mantén la anterior durante un periodo definido.
- Versión mínima soportada: la app debe poder consultar al iniciar si su versión sigue siendo compatible y, si no lo es, pedir al usuario que actualice.
- Configuración remota: poder activar o desactivar funciones desde el servidor permite reaccionar sin publicar una nueva versión.
// Respuesta de ejemplo: GET /api/v1/app/handshake?version=2.4.1&platform=android
{
"min_supported_version": "2.4.0",
"latest_version": "2.5.2",
"force_update": false,
"features": {
"nuevo_checkout": true,
"pagos_con_qr": true
}
}
Antes de publicar un cambio en la API, verifica que la versión anterior de la app sigue funcionando con él. Es más barato que descubrirlo por las reseñas de los usuarios.
¿Una API general o un backend por cliente?
Las pantallas de una app móvil suelen necesitar datos distintos que las de la web, y en menos llamadas, porque cada solicitud por red móvil es costosa. El patrón backend for frontend (BFF) agrega una capa delgada por tipo de cliente que compone las respuestas a partir de la API general.
| Criterio | Una API general para todos | Backend for frontend |
|---|---|---|
| Complejidad | Menor: un solo servicio. | Mayor: una capa más por cliente. |
| Ajuste a cada pantalla | Limitado: el cliente arma la información con varias llamadas. | Alto: respuestas a la medida de cada cliente. |
| Cuándo conviene | Clientes con necesidades parecidas o equipos pequeños. | Clientes muy distintos o muchas llamadas por pantalla. |
Si se usa un BFF, debe limitarse a componer y adaptar datos. Las reglas de negocio siguen en la API principal; de lo contrario, se vuelve a duplicar la lógica.
Autenticación en aplicaciones móviles
- No incluyas secretos en la app: cualquier valor dentro del instalable puede extraerse.
- Usa tokens de acceso de vida corta y tokens de renovación que puedan revocarse, por ejemplo al cerrar sesión o al reportar un teléfono perdido.
- Guarda los tokens en el almacenamiento seguro del sistema (Keychain en iOS, Keystore en Android), no en preferencias sin cifrar.
- Para inicio de sesión con proveedores externos, sigue los flujos recomendados para aplicaciones nativas (OAuth 2.0 con PKCE).
Profundizamos en controles de servidor en seguridad de APIs.
Redes inestables
Un teléfono cambia de red, entra en un ascensor o pierde señal a mitad de una operación. El diseño debe asumirlo:
- Tiempos de espera y reintentos en la app, solo para operaciones seguras de repetir.
- Claves de idempotencia en operaciones como crear un pedido: si el usuario pulsa dos veces o la app reintenta tras perder la respuesta, el servidor reconoce la operación y no la duplica.
- Estados intermedios claros: «enviando», «pendiente de confirmación», en lugar de mostrar éxito antes de que el servidor responda.
- Trabajo sin conexión solo donde aporte valor real, con una estrategia definida para resolver conflictos al sincronizar.
Diseño de respuestas
- Pagina las listas y limita su tamaño.
- Evita que una pantalla necesite muchas llamadas encadenadas.
- Devuelve fechas en un formato estándar con zona horaria y deja el formato de presentación al cliente.
- Usa códigos y mensajes de error consistentes, que la app pueda interpretar para mostrar un mensaje útil.
Notificaciones push: un aviso, no la fuente de verdad
Las notificaciones push no tienen entrega garantizada: pueden llegar tarde, duplicadas o no llegar. Úsalas para avisar que algo cambió, pero haz que la app consulte el estado real al servidor al abrirse. Un pedido no debe depender de que una notificación llegue para mostrarse como confirmado.
Errores frecuentes
- Calcular precios o permisos en la aplicación cliente.
- Romper la API para versiones publicadas de la app.
- Incluir claves de servicios de terceros en el código de la app.
- No contemplar el doble envío de operaciones por reintentos o doble toque.
- Depender de notificaciones push para mostrar el estado correcto.
Lista de verificación
- Las reglas de negocio están solo en el backend.
- Los cambios de API son compatibles o están versionados.
- La app puede verificar si su versión sigue siendo soportada.
- No hay secretos en las aplicaciones cliente.
- Las operaciones de creación admiten idempotencia.
- La app consulta el estado real y no depende de las notificaciones.
Preguntas frecuentes
¿Durante cuánto tiempo debo mantener una versión antigua de la API?
Hasta que la proporción de usuarios con versiones antiguas de la app sea aceptablemente baja según tu negocio. Medir qué versiones están en uso es la base para decidirlo.
¿Conviene usar GraphQL para evitar el BFF?
Puede ser una alternativa para que cada cliente pida exactamente los datos que necesita, aunque introduce sus propias consideraciones de rendimiento, seguridad y caché. La elección depende del equipo y del caso.