Use Cases (Aktualisiert: 3.6.2026)

gRPC-Entwicklung mit Claude Code: Protobuf, Streaming und Betrieb

Baue mit Claude Code einen ausführbaren gRPC-Dienst mit Protobuf, Fristen, Streaming, Auth und Monitoring.

gRPC-Entwicklung mit Claude Code: Protobuf, Streaming und Betrieb

Erst der Vertrag, dann die Implementierung

gRPC ist ein Rahmen für entfernte Prozeduraufrufe. Ein Client ruft eine Methode eines anderen Dienstes wie eine lokale Funktion auf, während die Kommunikation über das Netzwerk läuft. Protocol Buffers beschreibt den Vertrag: Dienst, Methoden, Anfragen, Antworten und Feldnummern. Claude Code soll diesen Vertrag zuerst verstehen, bevor Server und Client entstehen.

Nutze die offiziellen Quellen während der Arbeit: gRPC Introduction, Core concepts, Node basics, Deadlines, Status Codes, Authentication, OpenTelemetry Metrics und den Protocol Buffers proto3 guide.

Passende interne Artikel sind API-Entwicklung für Produktion, Microservices mit Claude Code, API-Versionierung und Teststrategien.

Konkrete Einsatzfälle

gRPC ist nicht automatisch die richtige Wahl, nur weil es effizient ist. Es lohnt sich besonders, wenn ein typisierter Vertrag und klare Fehlerzustände den Betrieb vereinfachen.

EinsatzfallWarum gRPC passtAuftrag an Claude Code
Interne Dienste für Bestellung, Lager, AbrechnungDer Vertrag verhindert stille Abweichungen.proto, Server, Client und Statuscodes schreiben
Große ExporteServer-Streaming vermeidet eine riesige Antwortreturns (stream Item) und Abbruchbehandlung umsetzen
Teams mit Go, Node und PythonEin Schema führt mehrere SprachenErzeugungsbefehle, Ordner und CI dokumentieren
Interne Werkzeuge und KI-AgentenExplizite Methoden sind weniger mehrdeutigBeispielclient, Auth-Metadaten, Fristen und Logs ergänzen

Masas Erfahrung aus kleinen Diensten: Eine zu breite Search-Methode wirkt anfangs bequem, wird aber schwer zu versionieren. Lesen, Schreiben und Streaming früh zu trennen macht Claude-Code-Änderungen überprüfbarer.

Ausführbares Node-gRPC-Beispiel

Dieses Beispiel lädt die .proto-Datei mit @grpc/proto-loader. Für den ersten lokalen Nachweis ist kein protoc nötig.

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;
});

Server starten:

npm run server

Client starten:

npm run client

Schema, Sicherheit und Ausfälle

Bei Protocol Buffers ist die Wiederverwendung von Feldnummern der gefährlichste Fehler. Veröffentliche Nummern bleiben stabil. Entfernte Felder werden mit Nummer und Name reserviert.

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";
}

Fristen gehören zum Entwurf. Die gRPC-Dokumentation weist darauf hin, dass ein Client ohne Frist unbegrenzt warten kann. Streaming ist gut für Exporte, muss aber Abbruch und Speicherverbrauch sauber behandeln.

Das Beispiel nutzt createInsecure() nur lokal. In Produktion brauchst du TLS: grpc.ServerCredentials.createSsl(...) auf dem Server und grpc.credentials.createSsl(rootCert) im Client. Ein Token in Metadaten schützt nicht, wenn der Kanal unverschlüsselt ist.

Monitoring sollte Methode, Status, Dauer, Abbruch, Fristablauf und nicht erreichbare Backends zeigen. OpenTelemetry-Metriken für gRPC sind dafür eine sinnvolle Basis. Gib nicht alles als UNKNOWN zurück; unterscheide INVALID_ARGUMENT, NOT_FOUND, UNAUTHENTICATED, DEADLINE_EXCEEDED, UNAVAILABLE und RESOURCE_EXHAUSTED. Schreibende Aufrufe sollten nur mit Idempotenzschlüssel automatisch wiederholt werden.

Prompt für Claude Code

Implementiere gRPC TaskService.
Bedingungen:
- Zuerst proto/task.proto erstellen
- Node.js, @grpc/grpc-js und @grpc/proto-loader verwenden
- CreateTask, GetTask und ListTasks als Server-Streaming implementieren
- Jeden Client-RPC mit deadline versehen
- authorization metadata prüfen
- Dokumentieren, dass Produktion createInsecure durch TLS ersetzt
- npm run client ausführen und Ausgabe berichten
Änderbare Dateien:
- proto/task.proto
- server.js
- client.js
- package.json

Review-Prompt:

Prüfe diese gRPC-Implementierung mit findings first.
Kontrolliere Feldnummern, Schemaentwicklung, deadline, cancellation,
status code, Speicherverhalten beim Streaming, TLS/auth und observability.
Sortiere nach Schweregrad und nenne konkrete Dateien.

CTA und Prüfergebnis

Wenn du allein lernst, beginne mit dem kostenlosen Claude-Code-Spickzettel und baue dieses Beispiel in einem Wegwerfprojekt nach. Teams, die .proto-Regeln, CI-Gates, Review-Prompts, TLS und Monitoring einführen wollen, können mit Claude-Code-Training und Beratung starten. Wiederverwendbare Materialien liegen unter ClaudeCodeLab-Produkte.

Für diese Überarbeitung wurde das Beispiel in einem temporären Verzeichnis mit Node v24.14.1 und npm 11.11.0 ausgeführt. npm install, node server.js und node client.js liefen durch; der Client zeigte created, fetched und streamed: 1. go, protoc und die Protobuf-Erweiterungen für Go waren auf diesem Rechner nicht vorhanden, daher verwendet der Artikel bewusst den lokal geprüften Node-Weg.

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

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.