Дедлайн - момент, после которого ответ больше не нужен. Он передаётся по цепочке вызовов и уменьшается на каждом шаге.

На клиенте

ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond)
defer cancel()
order, err := client.GetOrder(ctx, request)

Если предыдущий этап потратил 300 мс, следующий получает уже не 500, а оставшиеся 200. Поэтому дедлайны не перемножаются.

общий дедлайн 500 мс сервис A 300 мс сервис B 200 мс

Сервис B получает только оставшиеся 200 мс, а не новые 500. Общий дедлайн включает работу всех предыдущих шагов.

Сервер проверяет ctx.Done() на длительных операциях и возвращает DeadlineExceeded или соответствующую ошибку контекста.

Отмена

Клиентская отмена закрывает поток и доходит до сервера. Это не гарантирует мгновенную остановку: репозиторий, HTTP-клиент и фоновые задачи должны принимать тот же контекст.

context.Background() внутри обработчика обрывает цепочку, поэтому его не используют для новых сетевых вызовов.

Metadata

Metadata похожа на HTTP-заголовки:

md := metadata.New(map[string]string{"authorization": "Bearer " + token, "x-request-id": requestID})
ctx = metadata.NewOutgoingContext(ctx, md)

Сервер читает metadata.FromIncomingContext(ctx). Туда кладут токен и request ID, а не большие бизнес-объекты. Значения секретов не пишут в логи.

Где заканчивается ожидание

После DeadlineExceeded нельзя продолжать работу как ни в чём не бывало. Сетевой вызов уже отменён, а вот собственные горутины и записи в базу надо остановить отдельно через тот же ctx. Иначе клиент ушёл, а сервер продолжает тратить ресурсы и может записать результат, который никто не ждёт.

Ключи metadata пишут строчными ASCII-буквами: authorization, x-request-id. Не кладут туда nil, объекты Go и данные с произвольной кодировкой; для бинарных значений есть ключи с суффиксом -bin.

Если токен нужен только внутри одного метода, не сохраняют его в долгоживущем контексте или глобальной переменной. Передают по вызову, а логи с metadata перед записью очищают от секретов.

Коротко

  • Дедлайн распространяется по цепочке и уменьшается на каждом шаге.
  • Отмена доезжает только через явно переданный контекст.
  • Metadata передаёт токен и корреляцию, не полезную нагрузку.
  • Секреты в metadata не логируются.