Go Academy · Lesson

Server and Client Streaming

Bidirectional streaming and backpressure

Lesson 3 of 413 steps

Server and Client Streaming is a free Go Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, and your progress syncs across the web and the CoddyKit app. The Go Academy course includes 4 lessons in total.

gRPC streaming types

gRPC supports three streaming modes beyond unary: server-streaming (server sends many), client-streaming (client sends many), and bidirectional (both stream).

Server streaming in .proto

Use the stream keyword before the response type:

service EventService {
    rpc ListEvents (ListEventsRequest) returns (stream Event);
}

Server streaming implementation

The server sends multiple messages by calling stream.Send() and returns nil when done:

func (s *server) ListEvents(req *pb.ListEventsRequest, stream pb.EventService_ListEventsServer) error {
    for _, event := range s.events {
        if err := stream.Send(event); err != nil { return err }
    }
    return nil
}

Client receiving a server stream

The client calls Recv() in a loop until io.EOF:

stream, err := client.ListEvents(ctx, &pb.ListEventsRequest{})
for {
    event, err := stream.Recv()
    if err == io.EOF { break }
    if err != nil { log.Fatal(err) }
    fmt.Println(event)
}

Client streaming in .proto

Use stream before the request type:

service UploadService {
    rpc Upload (stream Chunk) returns (UploadResponse);
}

Client streaming implementation

The client sends multiple messages then closes the stream with CloseAndRecv:

stream, _ := client.Upload(ctx)
for _, chunk := range chunks {
    stream.Send(chunk)
}
resp, err := stream.CloseAndRecv()

Server receiving client stream

Call stream.Recv() in a loop until io.EOF, then return the final response:

func (s *server) Upload(stream pb.UploadService_UploadServer) error {
    for {
        chunk, err := stream.Recv()
        if err == io.EOF {
            return stream.SendAndClose(&pb.UploadResponse{Received: total})
        }
        if err != nil { return err }
        total += len(chunk.Data)
    }
}

Bidirectional streaming

Both client and server can send and receive independently. Declare with stream on both sides in the .proto.

service ChatService {
    rpc Chat (stream Message) returns (stream Message);
}

Bidirectional server implementation

Server receives in a goroutine and sends independently:

func (s *server) Chat(stream pb.ChatService_ChatServer) error {
    for {
        msg, err := stream.Recv()
        if err == io.EOF { return nil }
        if err != nil { return err }
        stream.Send(&pb.Message{Text: "echo: " + msg.Text})
    }
}

Flow control

gRPC uses HTTP/2 flow control to prevent fast senders from overwhelming slow receivers. Calls to Recv() naturally apply back-pressure — sending blocks when the receiver is not reading.

Context cancellation

Pass a context with deadline or cancel to all streaming calls. The stream is cancelled when the context is done, which causes Recv/Send to return an error.

Quick Check

How does a server-streaming RPC server signal that it has finished sending?

Recap: gRPC Streaming

Key points:

  • Server stream: stream keyword on response; server calls Send()
  • Client stream: stream keyword on request; client calls Send() then CloseAndRecv()
  • Bidirectional: stream on both; independent Send and Recv goroutines
  • Context cancellation applies to all streaming calls
Free to start

Learn Go with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
51
Lessons
203

Frequently Asked Questions

Is the “Server and Client Streaming” lesson free?

Yes — any 3 lessons of the Go Academy learning path, including “Server and Client Streaming”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Go Academy course includes 4 lessons in total.

What will I learn in “Server and Client Streaming”?

Bidirectional streaming and backpressure You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Go Academy?

No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.

How long does the “Server and Client Streaming” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Go Academy lesson?

Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Protocol Buffers and .proto Files
  2. Implementing a Unary gRPC Service
  3. Server and Client Streaming
  4. gRPC Interceptors and Metadata
← Back to Go Academy