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.
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.
| Einsatzfall | Warum gRPC passt | Auftrag an Claude Code |
|---|---|---|
| Interne Dienste für Bestellung, Lager, Abrechnung | Der Vertrag verhindert stille Abweichungen | .proto, Server, Client und Statuscodes schreiben |
| Große Exporte | Server-Streaming vermeidet eine riesige Antwort | returns (stream Item) und Abbruchbehandlung umsetzen |
| Teams mit Go, Node und Python | Ein Schema führt mehrere Sprachen | Erzeugungsbefehle, Ordner und CI dokumentieren |
| Interne Werkzeuge und KI-Agenten | Explizite Methoden sind weniger mehrdeutig | Beispielclient, 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.
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.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Workflow von Obsidian zu CLAUDE.md
Obsidian-Arbeitsnotizen in CLAUDE.md-Betriebsnotizen verwandeln und Kontext nicht ständig neu erklären.
Claude Code Revenue CTA Routing: Artikel zu PDF, Gumroad und Beratung führen
Ein Claude-Code-Ablauf, der Leser nach Absicht zu Gratis-PDF, Gumroad oder Beratung führt.
Claude-Code-Team-Handoff-Regeln: Belege, Berechtigungen, Rollback und Umsatzpfade
Ein praktisches Claude-Code-Handoff für Review-Belege, Berechtigungen, Rollback, Gratis-PDF, Gumroad und Beratung.