NUCBA
23 de enero de 2026
producto

El error que cometen los devs backend al diseñar APIs

El error que cometen los devs backend al diseñar APIs Construiste una API REST impecable: endpoints lógicos, arquitectura limpia, base de datos optimizada. El frontend la integr...

Equipo NUCBA

Equipo NUCBA

6 min de lectura

El error que cometen los devs backend al diseñar APIs

Construiste una API REST impecable: endpoints lógicos, arquitectura limpia, base de datos optimizada. El frontend la integra y aparecen los problemas: requests innecesarios, datos que faltan, respuestas imposibles de mostrar sin transformaciones. El error no está en tu código, está en que pensaste desde la base de datos hacia arriba, no desde la interfaz hacia abajo.

La mayoría de los desarrolladores backend diseñan APIs pensando en la estructura de datos, en las tablas, en la lógica del dominio. Pero una API que no considera cómo se va a consumir en la UI termina generando fricción, sobre-fetching, waterfalls de requests y componentes llenos de lógica de transformación que no deberían existir.

Por qué los devs backend ignoran la UI

Cuando trabajás del lado del servidor, tu contexto son las entidades, las relaciones, las queries. Diseñás endpoints que reflejan tu modelo de datos porque es lo que conocés, es lo que tiene sentido desde tu perspectiva técnica.

El problema es que la UI no consume entidades, consume vistas. Un usuario no ve "una tabla de órdenes con foreign keys a productos y usuarios". Ve un listado de compras con foto del producto, nombre, precio, estado del envío y un botón para cancelar. Todo eso, en un solo componente, sin pensar en joins ni relaciones.

Cuando tu API devuelve /orders con IDs de productos y /products/:id para cada detalle, estás forzando al frontend a hacer N+1 queries. Cuando devolvés campos que la UI nunca muestra o falta información que siempre se necesita, estás obligando a transformaciones constantes.

La desconexión entre backend y UI no es un problema de comunicación, es un problema de perspectiva. Y se soluciona diseñando desde donde el usuario interactúa: la interfaz.

Diseñar APIs desde los componentes, no desde las tablas

Acá está el cambio de mindset: antes de escribir un endpoint, preguntate qué va a mostrar la pantalla. No qué tablas necesitás consultar, no qué entidades están involucradas. Qué información necesita el componente para renderizar sin hacer malabares.

Ejemplo real: diseñar un dashboard de usuario

Supongamos que tenés que exponer datos para un dashboard. La estructura típica en DB:

users (id, name, email, created_at)
orders (id, user_id, total, status, created_at)
products (id, name, price)
order_items (order_id, product_id, quantity)

Approach tradicional (pensando desde la DB):

GET /users/:id
{
  "id": 123,
  "name": "Juan Pérez",
  "email": "juan@example.com",
  "created_at": "2023-01-15T10:00:00Z"
}

GET /orders?user_id=123
[
  { "id": 1, "user_id": 123, "total": 15000, "status": "delivered" },
  { "id": 2, "user_id": 123, "total": 8500, "status": "pending" }
]

El frontend tiene que:

  1. Pedir el usuario
  2. Pedir las órdenes
  3. Calcular stats (total gastado, cantidad de órdenes)
  4. Filtrar por estado si necesita

Approach UI-first:

GET /dashboard/user/:id
{
  "user": {
    "name": "Juan Pérez",
    "member_since": "Enero 2023"
  },
  "stats": {
    "total_orders": 12,
    "total_spent": 145000,
    "pending_orders": 2
  },
  "recent_orders": [
    {
      "id": 1,
      "date": "15 Mar 2024",
      "total": 15000,
      "status": "delivered",
      "status_label": "Entregado",
      "items_summary": "3 productos"
    }
  ]
}

La diferencia es brutal. El frontend hace un solo request y recibe exactamente lo que necesita mostrar: datos formateados, stats pre-calculados, labels traducidos. Nada de lógica de presentación del lado del cliente.

Pensar en estados de carga y errores desde el diseño

Una API pensada para UIs no solo devuelve datos, devuelve contexto. Porque los componentes no solo muestran contenido, muestran estados: cargando, vacío, error, éxito parcial.

Cuando diseñás un endpoint sin considerar estos casos, el frontend tiene que inventar soluciones:

// Frontend tratando de adivinar qué mostrar
const { data, error, loading } = useFetch('/products')

if (loading) return <Spinner />
if (error) return <Error message={error.message} /> // ¿Qué mensaje?
if (!data || data.length === 0) return <Empty /> // ¿Es un error o es normal?

Una API que piensa en UI incluye metadata:

GET /products?category=electronics
{
  "data": [],
  "meta": {
    "total": 0,
    "empty_state": {
      "title": "No hay productos en esta categoría",
      "message": "Probá buscando en otras categorías o volvé más tarde",
      "action": null
    }
  }
}

Ahora el frontend sabe exactamente qué mostrar y por qué. No está adivinando si es un error de permisos, un filtro sin resultados o una categoría nueva sin productos.

Lo mismo con errores:

// Error manejado desde backend
{
  "error": {
    "code": "INSUFFICIENT_STOCK",
    "message": "No hay stock suficiente para completar tu pedido",
    "user_message": "Algunos productos no tienen stock. Revisá tu carrito.",
    "recoverable": true,
    "action": {
      "label": "Ver carrito",
      "route": "/cart"
    }
  }
}

No estás devolviendo un 500 Internal Server Error genérico. Estás dando suficiente información para que la UI muestre un mensaje útil y una acción clara.

Optimizar para la jerarquía visual, no para la normalización

En base de datos, normalizás para evitar redundancia. En UIs, a veces necesitás redundancia para evitar requests y transformaciones.

Imaginate una lista de productos con reviews. Estructura normalizada:

GET /products
[
  { "id": 1, "name": "Teclado", "price": 12000 }
]

GET /reviews?product_id=1
[
  { "rating": 5, "text": "Excelente", "user_id": 44 }
]

Pero la UI necesita mostrar el promedio de rating junto al producto, no las reviews completas. Estás obligando a un request extra por algo que podrías incluir:

GET /products
[
  {
    "id": 1,
    "name": "Teclado",
    "price": 12000,
    "rating": {
      "average": 4.5,
      "count": 120
    }
  }
]

Duplicás el rating_average en lugar de calcularlo on-demand. Pero ahora el componente de producto tiene todo lo que necesita en un request. La optimización no es técnica, es de experiencia.

Checklist: diseñar APIs pensando en UI

Antes de escribir un endpoint, respondete:

  • ¿Qué componente va a consumir esto? Si no sabés, hablá con quien diseña la UI.
  • ¿Este endpoint devuelve exactamente lo que se muestra, o el frontend tiene que transformar? Si tiene que transformar, movelo al backend.
  • ¿Cuántos requests necesita el frontend para renderizar una pantalla completa? Si son más de 2-3, probablemente necesites agregar datos o crear un endpoint específico.
  • ¿Los estados vacíos y de error tienen contexto suficiente? No devuelvas solo [] o 500. Devolvé por qué y qué puede hacer el usuario.
  • ¿Los campos tienen los nombres y formatos que la UI espera? No hagas que el frontend traduzca created_at a "Hace 3 días". Hacelo vos.
  • ¿Estás optimizando para la base de datos o para la experiencia? A veces denormalizar un campo ahorra un montón de complejidad del otro lado.

Preguntas frecuentes

¿No estoy acoplando mi backend a una UI específica?
Estás acoplando tu API a casos de uso reales. Si cambia la UI pero el caso de uso es el mismo (mostrar un dashboard), la API sigue funcionando. Si el caso de uso cambia, tu API debería cambiar también. El problema no es el acoplamiento, es crear abstracciones prematuras que no sirven a nadie.

¿Qué hago si tengo múltiples clientes (web, mobile, etc)?
Podés crear endpoints específicos (/dashboard/mobile, /dashboard/web) o usar parámetros para customizar la respuesta. Lo importante es que cada cliente reciba lo que necesita, no una versión genérica que todos tienen que adaptar.

¿No es responsabilidad del frontend transformar datos?
El frontend debería transformar datos de presentación: cambiar colores, animaciones, layouts. No debería hacer lógica de negocio como calcular totales, formatear fechas según locale o decidir qué mensaje de error mostrar. Eso es backend.

¿Te gustó este artículo?

Descubre nuestros cursos y carreras para llevar tus habilidades al siguiente nivel.