← Blog
·11 blog.minutes

Diseño de APIs: REST vs GraphQL vs gRPC — Cómo Elegir

REST, GraphQL y gRPC resuelven cada uno un problema diferente. Esta guía compara sus filosofías de diseño, compensaciones y casos de uso ideales para que puedas tomar una decisión informada para tu próxima API.

Toda aplicación moderna se comunica con otras aplicaciones a través de APIs. La pregunta ya no es si construir una API, sino qué estilo de API construir. REST ha sido el predeterminado durante más de una década. GraphQL surgió como respuesta a la inflexibilidad de REST. gRPC adopta un enfoque completamente diferente basado en HTTP/2 y protocol buffers. Elegir entre ellos requiere entender no solo la sintaxis, sino la filosofía de diseño subyacente que cada uno representa.

Esta guía desglosa cada protocolo desde una perspectiva de diseño: cómo estructuras recursos o esquemas, cómo interactúan los clientes con tu API, cómo manejas el versionado y la paginación, y cómo los requisitos en tiempo real afectan la decisión. Al final, tendrás un marco para elegir la herramienta adecuada para tus restricciones específicas.

REST: Diseño orientado a recursos que la web entiende

REST (Transferencia de Estado Representacional) no es un protocolo. Es un estilo arquitectónico definido por Roy Fielding en su tesis doctoral de 2000. La idea central es que modelos tu dominio como recursos, cada uno identificado por una URL, y manipulas esos recursos a través de un conjunto uniforme de verbos HTTP: GET, POST, PUT, PATCH y DELETE.

Un buen diseño de API REST es diseño orientado a recursos. No diseñas endpoints en torno a acciones, sino en torno a sustantivos. En lugar de /createUser o /getUserById, diseñas POST /users y GET /users/:id. Esto parece una pequeña distinción, pero afecta profundamente cómo escala la API, cómo se documenta y cómo los clientes aprenden a usarla.

Un endpoint REST bien diseñado para un recurso de usuario se ve así:

GET /users/42
Accept: application/json

Response 200:
{
  "id": 42,
  "name": "Ada Lovelace",
  "email": "ada@example.com",
  "role": "admin",
  "createdAt": "2025-11-14T09:00:00Z"
}

La belleza de REST es su simplicidad. La URL identifica el recurso, el método HTTP identifica la operación y el cuerpo de la respuesta contiene la representación. Todo cliente HTTP en todos los lenguajes ya entiende este contrato. El caché funciona de fábrica a través de las cabeceras HTTP. Herramientas como OpenAPI (anteriormente Swagger) te permiten generar documentación, SDKs de cliente y stubs de servidor a partir de un solo archivo de esquema.

REST encuentra problemas cuando los clientes necesitan diferentes formas de datos. Un cliente móvil podría necesitar solo el nombre y el rol del usuario, mientras que un cliente de dashboard necesita el perfil completo con datos de organización anidados. Con REST, o construyes múltiples endpoints o fuerzas a cada cliente a descargar la representación completa y descartar lo que no necesita. Este es el problema de over-fetching, y fue la motivación principal para GraphQL.

GraphQL: Deja que el cliente describa exactamente lo que necesita

GraphQL, desarrollado por Meta y lanzado en 2015, adopta el enfoque opuesto. En lugar de que el servidor defina respuestas fijas, el cliente envía una consulta que describe exactamente los datos que quiere, y el servidor devuelve exactamente esa forma. Un endpoint, cualquier forma de respuesta.

Un esquema GraphQL define los tipos y relaciones en tu dominio. El cliente compone consultas contra este esquema, solicitando solo los campos que necesita. El mismo concepto de recursos anidados de REST se convierte en campos anidados en una consulta GraphQL, pero el cliente controla la profundidad y la selección.

// GraphQL schema (SDL)
type User {
  id: ID!
  name: String!
  email: String!
  role: Role!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  body: String!
}

enum Role { USER ADMIN MODERATOR }

type Query {
  user(id: ID!): User
}

Un cliente que necesita solo el nombre del usuario y los títulos de los posts envía una consulta que pide exactamente esos campos:

// Client query
query {
  user(id: 42) {
    name
    posts {
      title
    }
  }
}

// Response
{
  "data": {
    "user": {
      "name": "Ada Lovelace",
      "posts": [
        { "title": "Notes on the Analytical Engine" }
      ]
    }
  }
}

El principio de diseño clave en GraphQL es que el esquema es el contrato. El esquema define lo que es posible, y el cliente decide qué solicitar de las opciones disponibles. Esto elimina el over-fetching, reduce el número de solicitudes de red (una sola consulta puede reemplazar múltiples viajes de ida y vuelta de REST) y da a los equipos de frontend independencia de los cambios de backend porque los nuevos requisitos del cliente no siempre requieren nuevos endpoints.

GraphQL introduce complejidad propia. El rendimiento de las consultas es más difícil de predecir porque el cliente controla lo que se carga. El problema N+1, donde resolver campos anidados desencadena una consulta de base de datos independiente para cada registro padre, requiere soluciones de batching como DataLoader. El almacenamiento en caché a nivel HTTP no funciona porque cada consulta golpea el mismo endpoint POST, por lo que son necesarias estrategias de caché a nivel de aplicación. Y la curva de aprendizaje para resolvers, mutaciones, suscripciones y tipos de entrada es más pronunciada que el modelo directo de URL-y-verbo de REST.

GraphQL da a los equipos de frontend independencia de los cambios de backend. Pero esa independencia conlleva la responsabilidad de entender las características de rendimiento de cada consulta que tu cliente envía al servidor.

gRPC: RPC de alto rendimiento construido sobre HTTP/2 y protobuf

gRPC, desarrollado originalmente por Google, adopta otro enfoque más. En lugar de recursos y consultas, gRPC modela las APIs como llamadas a procedimientos remotos: defines un servicio con métodos, y los clientes llaman a esos métodos como si fueran funciones locales. La diferencia técnica clave es que gRPC usa Protocol Buffers (protobuf) para la serialización en lugar de JSON, y HTTP/2 para el transporte en lugar de HTTP/1.1.

Una definición de servicio protobuf no se parece en nada a un endpoint REST o un esquema GraphQL:

syntax = "proto3";

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListUsers (ListUsersRequest) returns (ListUsersResponse);
  rpc CreateUser (CreateUserRequest) returns (User);
  rpc StreamUserUpdates (StreamRequest) returns (stream UserUpdate);
}

message GetUserRequest {
  int32 id = 1;
}

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
  Role role = 4;
  string created_at = 5;
}

enum Role { ADMIN = 0; USER = 1; }

message StreamRequest {}

message UserUpdate {
  User user = 1;
  string event_type = 2;
}

Protobuf serializa a un formato binario compacto que es significativamente más pequeño que JSON y más rápido de analizar. Combinado con la multiplexación de HTTP/2 (múltiples flujos sobre una sola conexión), gRPC logra una latencia dramáticamente menor y un rendimiento mayor que REST o GraphQL para comunicaciones de alto volumen. Esto convierte a gRPC en la opción dominante para la comunicación entre microservicios, donde cada milisegundo de sobrecarga de serialización y cada byte en el cable importan.

gRPC también soporta de forma nativa cuatro tipos de streaming: unario (una solicitud, una respuesta), server-streaming (una solicitud, flujo de respuestas), client-streaming (flujo de solicitudes, una respuesta) y bidireccional (ambos lados transmiten simultáneamente). Esto lo convierte en la opción más fuerte para APIs en tiempo real entre los tres protocolos.

La compensación es que gRPC es más difícil de usar desde navegadores. Los clientes de navegador no pueden acceder a los servicios gRPC directamente porque carecen de control detallado sobre los frames HTTP/2. gRPC-Web existe como solución alternativa, pero añade complejidad. Los mensajes protobuf no son legibles por humanos en tránsito, lo que hace que la depuración sea más difícil: necesitas herramientas como grpcurl o un servicio de reflexión para inspeccionar el tráfico. Y el ecosistema de documentación de APIs es menos maduro que OpenAPI o el sistema de introspección de GraphQL.

Cómo se comparan en aspectos prácticos

Elegir entre REST, GraphQL y gRPC rara vez es una decisión puramente técnica. La elección correcta depende de quiénes son tus clientes, qué tipo de datos necesitan y las restricciones de tu red e infraestructura. Así es como se compara cada protocolo en los aspectos prácticos que más importan en producción.

Versionado de APIs

REST maneja el versionado a través de la URL o la cabecera Accept. /v1/users y /v2/users pueden coexistir indefinidamente, permitiendo que los clientes migren a su propio ritmo. Esto es simple y probado en batalla, pero fomenta la duplicación: el endpoint v2 a menudo duplica la mayor parte de la lógica de v1 con algunos cambios. GraphQL evita el versionado por completo evolucionando el esquema. Los campos obsoletos se decoran con una directiva @deprecated y permanecen en el esquema hasta que todos los clientes hayan migrado. Esto funciona bien cuando controlas todos los clientes, pero puede causar fricción en APIs públicas donde los clientes se actualizan lentamente. El esquema protobuf de gRPC es compatible hacia adelante por diseño: puedes añadir campos sin romper clientes existentes, y los campos obsoletos se eliminan después de un período de migración. Esta es la estrategia de versionado más elegante de las tres, pero requiere disciplina para nunca renombrar o eliminar un campo sin un ciclo de obsolescencia.

Patrones de paginación

La paginación REST típicamente se hace con paginación basada en cursor usando un campo nextCursor, o paginación basada en offset con parámetros page y limit. El principio de diseño es que la respuesta contiene un enlace o token siguiente, y el cliente lo sigue. La paginación GraphQL usa la especificación Relay Connection, que envuelve las listas en edges con cursores e información de página: más verbosa pero más consistente que los enfoques REST ad-hoc. La paginación gRPC se maneja manualmente en los mensajes de solicitud y respuesta, usualmente con un campo page_token y page_size. No hay un estándar, pero el esquema protobuf hace explícito el contrato.

  • REST: la paginación basada en cursor con nextCursor en la respuesta es el patrón recomendado para APIs de producción
  • GraphQL: la especificación Relay Connection proporciona un modelo de paginación estandarizado con hasNextPage, hasPreviousPage y cursores
  • gRPC: la paginación se define en tus mensajes proto; un patrón común es incluir page_token y page_size en la solicitud y next_page_token en la respuesta

Autenticación y autorización

Los tres protocolos dependen de la misma seguridad de transporte subyacente. REST típicamente usa tokens Bearer en la cabecera Authorization. GraphQL sigue el mismo patrón: como todas las solicitudes pasan por un único endpoint POST, el token se valida en la capa de GraphQL o en un middleware. gRPC usa interceptores para adjuntar metadatos de autenticación a cada llamada, generalmente en forma de tokens JWT transportados en las cabeceras de metadatos de gRPC. Ninguno de los tres protocolos prescribe un método de autenticación específico: la elección de OAuth2, claves API o autenticación basada en sesiones es ortogonal al estilo de API.

Limitación de tasa

La limitación de tasa es más simple con REST porque cada endpoint representa una operación acotada. Cuentas las solicitudes por endpoint por cliente y devuelves 429 Too Many Requests cuando se supera el límite. GraphQL hace que la limitación de tasa sea más difícil porque una sola consulta puede desencadenar cantidades de trabajo muy diferentes: una consulta para un campo podría costar una búsqueda en la base de datos, mientras que una consulta con relaciones profundamente anidadas podría costar cincuenta. Las APIs GraphQL típicamente implementan limitación de tasa basada en costo, donde cada campo tiene un peso y el costo total de la consulta se calcula antes de la ejecución. La limitación de tasa de gRPC es similar a REST pero opera a nivel de método: cuentas llamadas RPC por método por cliente, con la consideración adicional de que las llamadas de streaming consumen recursos durante su duración, no solo en su inicio.

APIs en tiempo real y streaming

REST puede manejar actualizaciones en tiempo real a través de WebSockets o Server-Sent Events (SSE), pero ninguno es parte de la especificación REST: son protocolos separados añadidos junto a la API HTTP. GraphQL tiene suscripciones, que son una parte de primera clase de la especificación. Un cliente se suscribe a un evento y recibe actualizaciones a través de una conexión WebSocket cada vez que ocurre el evento. gRPC tiene la historia de tiempo real más fuerte con su streaming bidireccional nativo sobre HTTP/2. Una sola llamada gRPC puede transmitir datos en ambas direcciones simultáneamente, lo que es ideal para dashboards en tiempo real, aplicaciones de chat y sistemas impulsados por eventos. Si la comunicación en tiempo real es un requisito principal, el streaming de gRPC es la opción más madura y con mejor rendimiento, seguida por las suscripciones de GraphQL, seguidas por REST más WebSockets.

Documentación y experiencia del desarrollador

REST tiene el ecosistema de documentación más fuerte gracias a OpenAPI (anteriormente Swagger). Una especificación OpenAPI describe cada endpoint, parámetro de solicitud, esquema de respuesta y método de autenticación en un archivo YAML o JSON legible por máquina. Herramientas como Swagger UI renderizan esto en una página de documentación interactiva, y los generadores de código producen SDKs de cliente para docenas de lenguajes. La madurez de este ecosistema significa que un nuevo desarrollador puede pasar de leer una especificación OpenAPI a hacer su primera llamada API exitosa en minutos.

GraphQL tiene introspección: un sistema incorporado donde consultas el esquema de la API a través de un endpoint especial. Herramientas como GraphiQL y Apollo Studio Explorer permiten a los desarrolladores navegar por el esquema, escribir consultas con autocompletado y ver documentación en línea. Esta es una gran experiencia para desarrolladores que ya saben que tu API existe, pero no ayuda con la descubribilidad en motores de búsqueda o mercados de APIs externos de la manera que lo hace una especificación OpenAPI.

gRPC se basa en archivos proto como su fuente de verdad. El archivo proto es tanto el esquema como la documentación. Herramientas como protoc-gen-doc generan documentación de referencia a partir de archivos proto, y la reflexión de gRPC permite a los clientes descubrir servicios dinámicamente. La experiencia del desarrollador para gRPC está mejorando, pero aún va por detrás de REST y GraphQL en madurez de herramientas, especialmente fuera del ecosistema de microservicios.

Cuándo usar cada uno

REST es la elección correcta cuando tu API es consumida por desarrolladores externos, cuando necesitas la máxima interoperabilidad y cuando tus clientes necesitan caching HTTP estándar. Es el predeterminado más seguro porque todos los lenguajes, frameworks y proxies entienden HTTP. Si estás construyendo una API pública, empieza con REST.

GraphQL es la elección correcta cuando tu API tiene múltiples tipos de cliente con diferentes requisitos de datos, cuando los equipos de frontend necesitan moverse independientemente de los cambios de backend y cuando quieres reducir el número de solicitudes de red. Destaca en aplicaciones orientadas al consumidor con clientes móviles y web que necesitan diferentes formas de los mismos datos.

gRPC es la elección correcta para la comunicación interna entre microservicios, para sistemas de alto rendimiento donde la sobrecarga de serialización importa y para aplicaciones de streaming en tiempo real. Si estás construyendo un sistema donde ambos extremos están bajo tu control y el rendimiento es la preocupación principal, gRPC es la opción más fuerte.

Ninguno de estos protocolos es mutuamente excluyente. Una arquitectura de producción común usa gRPC para la comunicación entre servicios detrás del firewall, expone una puerta de enlace GraphQL que agrega datos de múltiples servicios gRPC y proporciona una API REST para clientes externos. La pregunta no es qué protocolo usar en todas partes, sino qué protocolo usar para cada interfaz en tu sistema. Entender la filosofía de diseño detrás de cada uno te da el criterio para hacer esa elección correctamente.