SincroDev Logo SincroDev

El Viaje de una Petición GraphQL: Del cliente al resolver y de vuelta


GraphQL promete algo muy atractivo: pedir exactamente los datos que necesitas, ni más ni menos.

Pero entre ese query elegante en el frontend y la respuesta JSON final, pasan muchas cosas: parsing, validación, ejecución de resolvers, llamadas a bases de datos y optimizaciones para evitar cuellos de botella.

Este es el viaje completo de una petición GraphQL.

Escena 1: El cliente construye la consulta

Un cliente (web, móvil o backend) envía una operación como esta:

query GetUserDashboard($userId: ID!) {
  user(id: $userId) {
    id
    name
    plan
    projects {
      id
      name
      status
    }
  }
}

Y además manda variables:

{
  "userId": "u_123"
}

A diferencia de REST (múltiples endpoints), aquí casi siempre hay un endpoint único, por ejemplo /graphql.

Escena 2: Llega al servidor GraphQL

El servidor recibe query + variables + operationName y comienza una pipeline típica:

  1. Parse: convierte el texto a un AST (árbol sintáctico).
  2. Validate: verifica que el query cumple el schema.
  3. Execute: recorre campos y ejecuta resolvers.
  4. Format response: arma el JSON final con data y posibles errors.

Si falla parse o validación, no llega a ejecutar resolvers.

Escena 3: El Schema como contrato

GraphQL se apoya en un schema fuertemente tipado.

Ejemplo simplificado:

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

type User {
  id: ID!
  name: String!
  plan: String!
  projects: [Project!]!
}

type Project {
  id: ID!
  name: String!
  status: String!
}

Ese contrato define qué campos existen, qué argumentos aceptan y qué tipo devuelve cada uno.

Escena 4: Ejecución de resolvers

Cuando empieza execute, GraphQL resuelve el árbol campo por campo.

  • Query.user(id) llama al resolver de usuario.
  • Luego resuelve user.id, user.name, user.plan.
  • Después entra a user.projects y resuelve cada proyecto.

Modelo mental:

Query.user -> User
  |- id
  |- name
  |- plan
  |- projects -> [Project]
       |- id
       |- name
       |- status

Cada campo puede tener su propio resolver. Allí vive la lógica de negocio real.

Escena 5: El problema clásico N+1

Aquí aparece una trampa común.

Si projects dispara una consulta por cada usuario o por cada proyecto relacionado, terminas con decenas o cientos de queries a la base:

  • 1 query para usuarios
  • N queries para proyectos por usuario

Eso es el N+1 problem.

Solución habitual: DataLoader (batching + caching por request)

  • Agrupa múltiples lecturas en una sola consulta.
  • Cachea resultados durante esa petición.

Sin esto, GraphQL puede volverse lento aunque el query parezca pequeño.

Escena 6: Autorización y reglas

GraphQL no trae autorización “automática” por defecto. Debes implementarla.

Puntos clave:

  • Verificar identidad (authn) en el contexto de request.
  • Verificar permisos (authz) por campo o por recurso.
  • Evitar exponer campos sensibles por error en el schema.

Patrón práctico: validar permisos dentro de resolvers o directivas, nunca solo en el frontend.

Escena 7: Errores parciales y respuesta final

Una característica importante: GraphQL puede devolver datos parciales.

Formato típico:

{
  "data": {
    "user": {
      "id": "u_123",
      "name": "Ana",
      "projects": null
    }
  },
  "errors": [
    {
      "message": "No autorizado para ver projects",
      "path": ["user", "projects"]
    }
  ]
}

Esto permite que el cliente renderice lo que sí está disponible.

Escena 8: Performance real en producción

Para que una API GraphQL escale, normalmente necesitas:

  1. Persisted queries para reducir payload y controlar operaciones permitidas.
  2. Depth limit / complexity limit para evitar queries abusivas.
  3. Caching en varias capas (resolver, DB, CDN cuando aplique).
  4. Observabilidad por campo/resolver (latencia y errores).
  5. Timeouts y circuit breakers hacia servicios externos.

GraphQL no reemplaza buenas prácticas backend: las hace más visibles.

Comparativa rápida con REST

GraphQL brilla cuando:

  • Hay clientes con necesidades de datos distintas.
  • Quieres minimizar overfetching/underfetching.
  • Necesitas composición flexible de datos.

REST puede ser mejor cuando:

  • El dominio es simple y estable.
  • Priorizas caching HTTP estándar y operación muy predecible.
  • El equipo no necesita la flexibilidad extra de GraphQL.

Resumen del viaje

Una petición GraphQL recorre este camino:

  1. Cliente envía operación y variables.
  2. Servidor parsea y valida contra schema.
  3. Ejecuta resolvers según árbol de campos.
  4. Consulta servicios y bases (idealmente con batching).
  5. Aplica permisos y manejo de errores.
  6. Devuelve data + errors en JSON.

El valor de GraphQL no está solo en “pedir campos”. Está en diseñar una capa de ejecución eficiente, segura y observable entre el cliente y tus datos.