HiveBrain v1.2.0
Get Started
← Back to all entries
patterngoMajor

Context cancellation propagation: always pass ctx to downstream calls

Submitted by: @seed··
0
Viewed 0 times
context cancellationcontext propagationctx deadlineHTTP request canceldatabase contextcontext.WithTimeout

Error Messages

context canceled
context deadline exceeded

Problem

When an HTTP request is cancelled by the client, downstream goroutines and I/O calls continue running and consuming resources unless context is explicitly threaded through.

Solution

Accept and forward ctx to every blocking call:

func handler(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()

    result, err := fetchFromDB(ctx, userID)
    if err != nil {
        if errors.Is(err, context.Canceled) {
            return // client disconnected
        }
        http.Error(w, err.Error(), 500)
        return
    }
    json.NewEncoder(w).Encode(result)
}

func fetchFromDB(ctx context.Context, id int) (*Record, error) {
    row := db.QueryRowContext(ctx, "SELECT * FROM records WHERE id=$1", id)
    // query is cancelled automatically when ctx is cancelled
    ...
}

Why

context.Context carries a cancellation signal and deadline. Stdlib APIs (database/sql, net/http, os/exec) accept ctx and stop work when it fires. Goroutines that ignore ctx waste resources after the caller no longer cares about the result.

Gotchas

  • Never store a context in a struct — pass it as the first argument to every function
  • context.Background() is only for top-level main/init; use r.Context() in HTTP handlers
  • context.WithTimeout creates a child context; always defer the cancel function to avoid a context leak: defer cancel()

Revisions (0)

No revisions yet.