¿Cómo Construir una API Multi Protocolo con REST, GraphQL y gRPC?

Ashley Innocent

Ashley Innocent

13 March 2026

¿Cómo Construir una API Multi Protocolo con REST, GraphQL y gRPC?

TL;DR

Construye APIs multiprotocolo separando la lógica de negocio de las capas de protocolo. Crea una capa de dominio compartida, luego añade adaptadores REST, GraphQL y gRPC encima. Modern PetstoreAPI demuestra esta arquitectura con modelos de datos consistentes en los tres protocolos.

Introducción

Tu API sirve a clientes web, aplicaciones móviles y microservicios internos. Los clientes web quieren REST por su simplicidad. Las aplicaciones móviles quieren GraphQL para reducir la transferencia de datos. Los microservicios quieren gRPC por su rendimiento. ¿Construyes tres APIs separadas?

No. Construyes una API con tres capas de protocolo. La lógica de negocio permanece igual. Solo cambian los adaptadores de protocolo. Esta es la arquitectura de API multiprotocolo.

Modern PetstoreAPI implementa REST, GraphQL y gRPC desde un núcleo compartido. La misma lógica de la tienda de mascotas sirve a los tres protocolos con un comportamiento consistente.

💡
Si estás construyendo o probando APIs multiprotocolo, Apidog soporta pruebas de REST, GraphQL y gRPC en una sola herramienta. Puedes verificar que todos los protocolos devuelven datos consistentes y probar flujos de trabajo entre protocolos.
botón

En esta guía, aprenderás a arquitectar APIs multiprotocolo, implementar capas de protocolo y asegurar la consistencia entre protocolos utilizando Modern PetstoreAPI como referencia.

Arquitectura Multiprotocolo

Las APIs multiprotocolo separan las responsabilidades en capas.

Arquitectura por Capas

┌─────────────────────────────────────────┐
│  Capa de Protocolo (REST/GraphQL/gRPC)  │
├─────────────────────────────────────────┤
│  Capa de Aplicación (Casos de Uso)      │
├─────────────────────────────────────────┤
│  Capa de Dominio (Lógica de Negocio)    │
├─────────────────────────────────────────┤
│  Capa de Datos (Base de datos, Caché)   │
└─────────────────────────────────────────┘

Capa de Protocolo: Maneja HTTP, consultas GraphQL, llamadas gRPC Capa de Aplicación: Orquesta casos de uso (crear mascota, realizar pedido) Capa de Dominio: Reglas de negocio (validación, cálculos) Capa de Datos: Persistencia (base de datos, caché)

Principios Clave

1. Núcleo agnóstico al protocolo

La lógica de negocio no sabe de HTTP, GraphQL o gRPC. Trabaja con objetos de dominio.

2. Adaptadores de protocolo ligeros

Las capas de protocolo traducen entre formatos de protocolo y objetos de dominio. No contienen lógica de negocio.

3. Modelos de datos compartidos

Todos los protocolos utilizan los mismos modelos de dominio internamente, asegurando la consistencia.

4. Despliegue independiente

Cada protocolo puede desplegarse por separado si es necesario.

Capa de Dominio Compartida

La capa de dominio contiene lógica de negocio compartida entre todos los protocolos.

Modelos de Dominio

// Modelo de dominio (agnóstico al protocolo)
class Pet {
  id: string;
  name: string;
  species: Species;
  status: PetStatus;
  price: number;

  constructor(data: PetData) {
    this.validate(data);
    Object.assign(this, data);
  }

  validate(data: PetData): void {
    if (!data.name || data.name.length < 2) {
      throw new ValidationError('Name must be at least 2 characters');
    }
    if (data.price < 0) {
      throw new ValidationError('Price cannot be negative');
    }
  }

  adopt(userId: string): Order {
    if (this.status !== PetStatus.AVAILABLE) {
      throw new BusinessError('Pet is not available for adoption');
    }
    this.status = PetStatus.ADOPTED;
    return new Order({
      petId: this.id,
      userId,
      total: this.price
    });
  }
}

Este modelo funciona para REST, GraphQL y gRPC. Las reglas de validación y de negocio son las mismas.

Casos de Uso

// Caso de uso (agnóstico al protocolo)
class AdoptPetUseCase {
  constructor(
    private petRepository: PetRepository,
    private orderRepository: OrderRepository
  ) {}

  async execute(petId: string, userId: string): Promise<Order> {
    const pet = await this.petRepository.findById(petId);
    if (!pet) {
      throw new NotFoundError('Pet not found');
    }

    const order = pet.adopt(userId);
    await this.petRepository.save(pet);
    await this.orderRepository.save(order);

    return order;
  }
}

Este caso de uso funciona independientemente de si es llamado desde REST, GraphQL o gRPC.

Capa de Protocolo REST

La capa REST traduce las solicitudes HTTP a operaciones de dominio.

Controlador REST

// Adaptador REST
class PetsController {
  constructor(private adoptPetUseCase: AdoptPetUseCase) {}

  async adoptPet(req: Request, res: Response): Promise<void> {
    try {
      const { petId } = req.params;
      const { userId } = req.body;

      const order = await this.adoptPetUseCase.execute(petId, userId);

      res.status(201).json({
        id: order.id,
        petId: order.petId,
        userId: order.userId,
        total: order.total,
        status: order.status
      });
    } catch (error) {
      this.handleError(error, res);
    }
  }

  private handleError(error: Error, res: Response): void {
    if (error instanceof NotFoundError) {
      res.status(404).json({
        type: 'https://petstoreapi.com/errors/not-found',
        title: 'Not Found',
        status: 404,
        detail: error.message
      });
    } else if (error instanceof ValidationError) {
      res.status(400).json({
        type: 'https://petstoreapi.com/errors/validation-error',
        title: 'Validation Error',
        status: 400,
        detail: error.message
      });
    } else {
      res.status(500).json({
        type: 'https://petstoreapi.com/errors/internal-error',
        title: 'Internal Server Error',
        status: 500
      });
    }
  }
}

Rutas REST

app.post('/v1/pets/:petId/adopt', (req, res) =>
  petsController.adoptPet(req, res)
);

Puntos finales REST de Modern PetstoreAPI

Capa de Protocolo GraphQL

La capa GraphQL traduce las consultas GraphQL a operaciones de dominio.

Esquema GraphQL

type Pet {
  id: ID!
  name: String!
  species: Species!
  status: PetStatus!
  price: Float!
}

type Order {
  id: ID!
  petId: ID!
  userId: ID!
  total: Float!
  status: OrderStatus!
}

type Mutation {
  adoptPet(petId: ID!, userId: ID!): Order!
}

Resolvedor GraphQL

// Adaptador GraphQL
const resolvers = {
  Mutation: {
    adoptPet: async (
      _parent: any,
      args: { petId: string; userId: string },
      context: Context
    ): Promise<Order> => {
      try {
        return await context.adoptPetUseCase.execute(
          args.petId,
          args.userId
        );
      } catch (error) {
        throw new GraphQLError(error.message, {
          extensions: {
            code: error instanceof NotFoundError ? 'NOT_FOUND' :
                  error instanceof ValidationError ? 'BAD_USER_INPUT' :
                  'INTERNAL_SERVER_ERROR'
          }
        });
      }
    }
  }
};

Solicitud GraphQL

mutation {
  adoptPet(
    petId: "019b4132-70aa-764f-b315-e2803d882a24"
    userId: "user-123"
  ) {
    id
    total
    status
  }
}

Esquema GraphQL de Modern PetstoreAPI

Capa de Protocolo gRPC

La capa gRPC traduce los mensajes de Protocol Buffer a operaciones de dominio.

Definición de Protocol Buffer

syntax = "proto3";

package petstore.v1;

service PetService {
  rpc AdoptPet(AdoptPetRequest) returns (AdoptPetResponse);
}

message AdoptPetRequest {
  string pet_id = 1;
  string user_id = 2;
}

message AdoptPetResponse {
  string order_id = 1;
  string pet_id = 2;
  string user_id = 3;
  double total = 4;
  string status = 5;
}

Implementación del Servicio gRPC

// Adaptador gRPC
class PetServiceImpl implements IPetService {
  constructor(private adoptPetUseCase: AdoptPetUseCase) {}

  async adoptPet(
    call: ServerUnaryCall<AdoptPetRequest, AdoptPetResponse>,
    callback: sendUnaryData<AdoptPetResponse>
  ): Promise<void> {
    try {
      const { petId, userId } = call.request;

      const order = await this.adoptPetUseCase.execute(petId, userId);

      callback(null, {
        orderId: order.id,
        petId: order.petId,
        userId: order.userId,
        total: order.total,
        status: order.status
      });
    } catch (error) {
      callback({
        code: error instanceof NotFoundError ? status.NOT_FOUND :
              error instanceof ValidationError ? status.INVALID_ARGUMENT :
              status.INTERNAL,
        message: error.message
      });
    }
  }
}

Servicio gRPC de Modern PetstoreAPI

Cómo Modern PetstoreAPI Implementa el Multiprotocolo

Modern PetstoreAPI demuestra la arquitectura multiprotocolo con ejemplos reales.

Resumen de la Arquitectura

Modern PetstoreAPI
├── Capa de Dominio
│   ├── Mascota (entidad)
│   ├── Pedido (entidad)
│   └── Casos de Uso
│       ├── CrearMascota
│       ├── AdoptarMascota
│       └── RealizarPedido
├── Capa REST
│   ├── /v1/pets
│   ├── /v1/orders
│   └── Especificación OpenAPI 3.2
├── Capa GraphQL
│   ├── Resolvedores de consulta
│   ├── Resolvedores de mutación
│   └── Esquema GraphQL
└── Capa gRPC
    ├── ServicioMascota
    ├── ServicioPedido
    └── Definiciones .proto

Modelos de Datos Consistentes

Todos los protocolos devuelven los mismos datos:

REST:

{
  "id": "019b4132-70aa-764f-b315-e2803d882a24",
  "name": "Fluffy",
  "species": "CAT"
}

GraphQL:

{
  "data": {
    "pet": {
      "id": "019b4132-70aa-764f-b315-e2803d882a24",
      "name": "Fluffy",
      "species": "CAT"
    }
  }
}

gRPC:

{
  pet_id: "019b4132-70aa-764f-b315-e2803d882a24"
  name: "Fluffy"
  species: CAT
}

Mismos datos, diferentes formatos.

Validación Compartida

La validación ocurre en la capa de dominio, por lo que todos los protocolos aplican las mismas reglas:

// Validación de dominio (compartida)
if (name.length < 2) {
  throw new ValidationError('Name must be at least 2 characters');
}

REST devuelve:

{
  "type": "https://petstoreapi.com/errors/validation-error",
  "status": 400,
  "detail": "Name must be at least 2 characters"
}

GraphQL devuelve:

{
  "errors": [{
    "message": "Name must be at least 2 characters",
    "extensions": {"code": "BAD_USER_INPUT"}
  }]
}

gRPC devuelve:

code: INVALID_ARGUMENT
message: "Name must be at least 2 characters"

Misma validación, formatos de error específicos del protocolo.

Probando APIs Multiprotocolo con Apidog

Apidog soporta la prueba de los tres protocolos.

Probar Punto Final REST

POST https://petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24/adopt
Content-Type: application/json

{
  "userId": "user-123"
}

Probar Mutación GraphQL

mutation {
  adoptPet(
    petId: "019b4132-70aa-764f-b315-e2803d882a24"
    userId: "user-123"
  ) {
    id
    total
  }
}

Probar Servicio gRPC

grpc.petstore.v1.PetService/AdoptPet
{
  "pet_id": "019b4132-70aa-764f-b315-e2803d882a24",
  "user_id": "user-123"
}

Verificar Consistencia

Prueba que los tres protocolos devuelven los mismos datos:

  1. Llamar al punto final REST
  2. Llamar a la mutación GraphQL
  3. Llamar al servicio gRPC
  4. Comparar resultados

Apidog puede automatizar esta prueba entre protocolos.

Estrategias de Despliegue

Estrategia 1: Servicio Único

Desplegar todos los protocolos en un solo servicio:

┌─────────────────────────┐
│  Servicio PetstoreAPI   │
│  ├── REST (puerto 8080) │
│  ├── GraphQL (puerto 8081)│
│  └── gRPC (puerto 50051)│
└─────────────────────────┘

Ventajas: Despliegue simple, recursos compartidos Desventajas: Todos los protocolos escalan juntos

Estrategia 2: Servicios Separados

Desplegar cada protocolo por separado:

┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ Servicio REST│  │ Servicio GraphQL│  │ Servicio gRPC│
│ (puerto 8080)│  │ (puerto 8081)│  │ (puerto 50051)│
└──────────────┘  └──────────────┘  └──────────────┘
       │                 │                  │
       └─────────────────┴──────────────────┘
                         │
                  ┌──────────────┐
                  │ Núcleo Compartido│
                  │   Biblioteca │
                  └──────────────┘

Ventajas: Escalado independiente, aislamiento de protocolo Desventajas: Despliegue más complejo

Estrategia 3: Pasarela API

Usar una pasarela API para enrutar a los backends específicos de protocolo:

                ┌─────────────┐
                │ Pasarela API│
                └─────────────┘
                       │
        ┌──────────────┼──────────────┐
        │              │              │
┌───────▼──────┐ ┌────▼─────┐ ┌──────▼──────┐
│ Backend REST │ │ GraphQL  │ │ Backend gRPC│
└──────────────┘ └──────────┘ └─────────────┘

Ventajas: Enrutamiento centralizado, limitación de velocidad, autenticación Desventajas: Latencia adicional, complejidad de la pasarela

Modern PetstoreAPI utiliza la Estrategia 1 por simplicidad.

Conclusión

Las APIs multiprotocolo brindan a los clientes flexibilidad sin duplicar la lógica de negocio. Al separar las capas de protocolo de la lógica de dominio, puedes soportar REST, GraphQL y gRPC desde un núcleo compartido.

Modern PetstoreAPI demuestra esta arquitectura con modelos de datos consistentes, validación compartida y adaptadores específicos de protocolo. Ya sea que los clientes usen REST por simplicidad, GraphQL por flexibilidad o gRPC por rendimiento, acceden a la misma tienda de mascotas con las mismas reglas de negocio.

Prueba tus APIs multiprotocolo con Apidog para asegurar la consistencia entre protocolos. Explora Modern PetstoreAPI para ver la arquitectura multiprotocolo en acción.

botón

Preguntas Frecuentes

¿Necesito soportar los tres protocolos?

No. Comienza con REST para APIs públicas. Añade GraphQL si los clientes necesitan una recuperación de datos flexible. Añade gRPC para microservicios internos. Solo añade protocolos cuando tengas un caso de uso claro.

¿Cómo mantengo la consistencia entre protocolos?

Comparte la lógica de negocio en una capa de dominio. Los adaptadores de protocolo solo deben traducir formatos, no contener reglas de negocio. Prueba todos los protocolos para verificar que devuelven los mismos datos.

¿Puedo versionar los protocolos de forma independiente?

Sí. REST puede estar en v2 mientras GraphQL está en v1. Pero esto crea complejidad. Intenta mantener los protocolos sincronizados cuando sea posible.

¿Cómo manejo la autenticación entre protocolos?

Usa la misma autenticación en todos los protocolos. REST usa tokens Bearer en los encabezados. GraphQL usa los mismos tokens. gRPC usa metadatos. La capa de dominio valida los tokens de la misma manera.

¿Qué pasa con WebSocket y SSE?

WebSocket y SSE son protocolos de transporte, no protocolos de API. Puedes añadirlos junto con REST/GraphQL/gRPC para actualizaciones en tiempo real. Modern PetstoreAPI incluye ambos.

¿Cómo documento APIs multiprotocolo?

Usa OpenAPI para REST, el esquema GraphQL para GraphQL y archivos .proto para gRPC. Modern PetstoreAPI proporciona los tres en https://docs.petstoreapi.com/

¿Puedo usar bases de datos diferentes para protocolos diferentes?

Sí, pero crea desafíos de consistencia. Es mejor usar la misma capa de datos para todos los protocolos. Deja que los adaptadores de protocolo manejen las diferencias de formato.

¿Cómo pruebo APIs multiprotocolo?

Usa Apidog para probar todos los protocolos en una sola herramienta. Crea conjuntos de pruebas que verifiquen la consistencia entre protocolos. Prueba que REST, GraphQL y gRPC devuelven los mismos datos para las mismas operaciones.

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs