Use Cases (Mis à jour: 03/06/2026)

Développement gRPC avec Claude Code : Protobuf, flux et exploitation

Créez un service gRPC exécutable avec Claude Code, Protobuf, délais, flux, auth et observabilité.

Développement gRPC avec Claude Code : Protobuf, flux et exploitation

Commencer par le contrat

gRPC est un cadre d’appel distant : le client appelle une méthode d’un autre service comme une fonction locale, mais l’échange passe par le réseau. Protocol Buffers définit le contrat : services, méthodes, messages de requête, messages de réponse et numéros de champ. Avec Claude Code, ce contrat doit être fixé avant le serveur et le client.

Gardez les références officielles ouvertes : gRPC Introduction, Core concepts, Node basics, Deadlines, Status Codes, Authentication, OpenTelemetry Metrics et le guide Protocol Buffers proto3.

Pour compléter, lisez aussi développement API en production, microservices avec Claude Code, stratégie de versionnement API et stratégies de test.

Cas d’usage concrets

gRPC n’est pas seulement un choix de performance. Il devient utile quand le contrat typé, les erreurs explicites et la cohérence entre langages réduisent le risque.

Cas d’usagePourquoi gRPC convientTravail à confier à Claude Code
Services internes de commande, stock, facturationLe contrat limite les dérives entre équipesRédiger .proto, serveur, client et table des statuts
Export massifLe flux serveur évite une réponse énormeImplémenter returns (stream Item) et l’annulation
Équipe Go, Node, PythonUn schéma aligne plusieurs clientsDocumenter génération, dossiers et CI
Outils internes et agents IADes méthodes explicites évitent les appels flousAjouter client d’exemple, métadonnées d’auth, délais et journaux

Le retour d’expérience de Masa est simple : une méthode Search trop large semble pratique, puis devient difficile à faire évoluer. Séparez lecture, création et flux avant de demander à Claude Code d’écrire beaucoup de fichiers.

Exemple gRPC Node exécutable

Cet exemple utilise @grpc/proto-loader, donc la première vérification locale ne demande pas protoc.

mkdir claude-grpc-demo
cd claude-grpc-demo
npm init -y
npm install @grpc/grpc-js @grpc/proto-loader
mkdir proto

package.json :

{
  "type": "commonjs",
  "scripts": {
    "server": "node server.js",
    "client": "node client.js"
  },
  "dependencies": {
    "@grpc/grpc-js": "latest",
    "@grpc/proto-loader": "latest"
  }
}

proto/task.proto :

syntax = "proto3";

package tasks.v1;

service TaskService {
  rpc CreateTask(CreateTaskRequest) returns (Task);
  rpc GetTask(GetTaskRequest) returns (Task);
  rpc ListTasks(ListTasksRequest) returns (stream Task);
}

message Task {
  string id = 1;
  string title = 2;
  string status = 3;
  int64 created_at_unix = 4;
}

message CreateTaskRequest {
  string title = 1;
}

message GetTaskRequest {
  string id = 1;
}

message ListTasksRequest {
  int32 limit = 1;
}

server.js :

const path = require("node:path");
const { randomUUID } = require("node:crypto");
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");

const PROTO_PATH = path.join(__dirname, "proto", "task.proto");
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: false,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});
const taskProto = grpc.loadPackageDefinition(packageDefinition).tasks.v1;
const token = process.env.DEMO_TOKEN || "dev-token";
const tasks = new Map();

function grpcError(code, message) {
  const error = new Error(message);
  error.code = code;
  return error;
}

function assertAuthenticated(call) {
  const value = call.metadata.get("authorization")[0];
  if (value !== `Bearer ${token}`) {
    throw grpcError(grpc.status.UNAUTHENTICATED, "UNAUTHENTICATED");
  }
}

function createTask(call, callback) {
  try {
    assertAuthenticated(call);
    const title = String(call.request.title || "").trim();
    if (!title) {
      return callback(grpcError(grpc.status.INVALID_ARGUMENT, "INVALID_ARGUMENT: title"));
    }

    const task = {
      id: randomUUID(),
      title,
      status: "OPEN",
      createdAtUnix: String(Math.floor(Date.now() / 1000)),
    };
    tasks.set(task.id, task);
    callback(null, task);
  } catch (error) {
    callback(error);
  }
}

function getTask(call, callback) {
  try {
    assertAuthenticated(call);
    const task = tasks.get(call.request.id);
    if (!task) {
      return callback(grpcError(grpc.status.NOT_FOUND, "NOT_FOUND: task"));
    }
    callback(null, task);
  } catch (error) {
    callback(error);
  }
}

function listTasks(call) {
  try {
    assertAuthenticated(call);
    const limit = Math.min(Math.max(Number(call.request.limit) || 10, 1), 100);
    for (const task of Array.from(tasks.values()).slice(0, limit)) {
      call.write(task);
    }
    call.end();
  } catch (error) {
    call.destroy(error);
  }
}

const server = new grpc.Server();
server.addService(taskProto.TaskService.service, { createTask, getTask, listTasks });
server.bindAsync("127.0.0.1:50051", grpc.ServerCredentials.createInsecure(), (error, port) => {
  if (error) throw error;
  console.log(`TaskService listening on ${port}`);
});

client.js :

const path = require("node:path");
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");

const PROTO_PATH = path.join(__dirname, "proto", "task.proto");
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: false,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});
const taskProto = grpc.loadPackageDefinition(packageDefinition).tasks.v1;
const client = new taskProto.TaskService("127.0.0.1:50051", grpc.credentials.createInsecure());
const metadata = new grpc.Metadata();
metadata.set("authorization", `Bearer ${process.env.DEMO_TOKEN || "dev-token"}`);

function deadline(ms) {
  return new Date(Date.now() + ms);
}

function createTask(title) {
  return new Promise((resolve, reject) => {
    client.createTask({ title }, metadata, { deadline: deadline(1000) }, (error, task) => {
      if (error) return reject(error);
      resolve(task);
    });
  });
}

function getTask(id) {
  return new Promise((resolve, reject) => {
    client.getTask({ id }, metadata, { deadline: deadline(1000) }, (error, task) => {
      if (error) return reject(error);
      resolve(task);
    });
  });
}

function listTasks(limit) {
  return new Promise((resolve, reject) => {
    const rows = [];
    const stream = client.listTasks({ limit }, metadata, { deadline: deadline(1000) });
    stream.on("data", (task) => rows.push(task));
    stream.on("error", reject);
    stream.on("end", () => resolve(rows));
  });
}

async function main() {
  const created = await createTask("Claude Code gRPC");
  const fetched = await getTask(created.id);
  const rows = await listTasks(10);
  console.log(JSON.stringify({ created, fetched, streamed: rows.length }, null, 2));
  client.close();
}

main().catch((error) => {
  console.error(error.code, error.details || error.message);
  client.close();
  process.exitCode = 1;
});

Lancez le serveur :

npm run server

Puis le client :

npm run client

Évolution, sécurité et modes de panne

Dans Protocol Buffers, le piège principal est la réutilisation des numéros de champ. Ne changez pas un numéro déjà publié. Si vous supprimez un champ, réservez son numéro et son nom.

message Task {
  string id = 1;
  string title = 2;
  string status = 3;
  int64 created_at_unix = 4;
  optional string assignee_email = 5;
  reserved 6, 7;
  reserved "owner_email";
}

Les délais doivent être explicites. La documentation gRPC indique qu’un client sans délai peut attendre indéfiniment. Le flux serveur est pratique pour les exports, mais il doit gérer l’annulation et éviter de charger tout le résultat en mémoire.

L’exemple local utilise createInsecure() uniquement pour rester simple à copier. En production, utilisez TLS avec grpc.ServerCredentials.createSsl(...) côté serveur et grpc.credentials.createSsl(rootCert) côté client. Un jeton dans les métadonnées ne suffit pas si le canal n’est pas chiffré.

L’observabilité doit couvrir méthode, statut, durée, annulation, expiration de délai et indisponibilité du backend. Les métriques gRPC OpenTelemetry donnent une bonne base. Ne retournez pas tout en UNKNOWN : distinguez INVALID_ARGUMENT, NOT_FOUND, UNAUTHENTICATED, DEADLINE_EXCEEDED, UNAVAILABLE et RESOURCE_EXHAUSTED. Les appels d’écriture ne doivent être réessayés automatiquement qu’avec une clé d’idempotence.

Demande à envoyer à Claude Code

Implémente TaskService en gRPC.
Contraintes:
- Créer d'abord proto/task.proto
- Utiliser Node.js, @grpc/grpc-js et @grpc/proto-loader
- Implémenter CreateTask, GetTask et ListTasks en flux serveur
- Ajouter un deadline à chaque RPC client
- Vérifier authorization metadata
- Documenter que la production doit remplacer createInsecure par TLS
- Exécuter npm run client et rapporter la sortie
Fichiers modifiables:
- proto/task.proto
- server.js
- client.js
- package.json

Pour la revue :

Revois cette implémentation gRPC en findings first.
Vérifie réutilisation des numéros de champ, évolution du schéma,
deadline, cancellation, status code, mémoire du flux,
TLS/auth et observability. Classe par gravité avec fichiers précis.

CTA et résultat de vérification

Si vous apprenez seul, commencez avec la fiche gratuite Claude Code et adaptez cet exemple dans un projet jetable. Pour une équipe qui doit gérer .proto, CI, prompts de revue, TLS et observabilité, la suite naturelle est formation et conseil Claude Code. Les supports réutilisables sont dans les produits ClaudeCodeLab.

Pour cette mise à jour, l’exemple a été exécuté dans un dossier temporaire avec Node v24.14.1 et npm 11.11.0. npm install, node server.js et node client.js ont réussi, avec une sortie contenant created, fetched et streamed: 1. go, protoc et les greffons Protobuf Go n’étaient pas disponibles sur cette machine ; l’article utilise donc le chemin Node vérifié localement.

#Claude Code #gRPC #Protocol Buffers #microservices #backend
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.