Stage 3 · Build
Performance, Memory & Debugging
GODEBUG Runtime Flags
gctrace, schedtrace, http2debug, netdns, and reading runtime diagnostics.
GODEBUG Overview
GODEBUG is an environment variable that controls Go runtime behavior. It provides diagnostics, debugging, and compatibility flags without recompiling.
# Single flag
GODEBUG=gctrace=1 ./myapp
# Multiple flags
GODEBUG=gctrace=1,schedtrace=1000 ./myapp
# Set in Kubernetes
env:
- name: GODEBUG
value: "gctrace=1"
# Check current settings
import "runtime/debug"
fmt.Println(debug.SetTraceback("all"))GODEBUG flags are comma-separated key=value pairs. They are read at program start and cannot be changed at runtime. Some flags can be set with runtime/debug functions.
gctrace
gctrace prints garbage collection trace information. It shows GC timing, heap sizes, and pause durations. This is the primary tool for diagnosing GC issues.
# Enable gctrace
GODEBUG=gctrace=1 ./myapp
# Output format:
# gc 1 @0.012s 2%: 0.026+1.2+0.007 ms clock, 0.10+0.51/2.1/0+0.029 ms cpu, 4->5->2 MB, 5 MB goal, 8 P
# | | | | | | | |
# | | | | | | | +-- parallelism (P)
# | | | | | | +-- heap goal
# | | | | | +-- heap before/after GC
# | | | | +-- total CPU time
# | | | +-- wall clock time
# | | +-- GC fraction (CPU usage)
# | +-- GC number
# +-- time since start
# Example interpretation:
# gc 5 @1.234s 3%: 0.1+2.3+0.05 ms clock, 0.4+1.1/4.2/0+0.2 ms cpu, 8->10->6 MB, 10 MB goal, 8 P
# - GC #5 occurred at 1.234s
# - Used 3% of CPU
# - Pause: 0.1ms mark start, 2.3ms mark, 0.05ms mark termination
# - Heap: 8MB before, 10MB after, 6MB live
# - Goal: 10MB
# - 8 parallel goroutinesgctrace output shows the GC number, time, CPU usage, pause durations, heap sizes, and parallelism. Parse this to identify GC pressure, long pauses, and memory growth. High CPU percentage means GC is working hard.
schedtrace
schedtrace prints scheduler trace information. It shows goroutine scheduling, system calls, and processor utilization. Use it to diagnose scheduling issues.
# Enable schedtrace
GODEBUG=schedtrace=1000 ./myapp # Print every 1000ms
# With details
GODEBUG=schedtrace=1000,scheddetail=1 ./myapp
# Output format:
# SCHED 0ms: gomaxprocs=8 idleprocs=6 threads=12 spinningthreads=0 idlethreads=5 runqueue=0 [0 0 0 0 0 0 0 0]
# | | | | | | | |
# | | | | | | | +-- local run queues per P
# | | | | | | +-- global run queue
# | | | | | +-- threads waiting for work
# | | | | +-- threads doing work
# | | | +-- total threads
# | | +-- processors not running Go code
# | +-- number of Ps
# +-- time
# SCHED 1000ms: gomaxprocs=8 idleprocs=2 threads=15 spinningthreads=1 idlethreads=4 runqueue=12 [3 4 2 1 0 1 0 1]
# - 6 Ps are running Go code
# - 12 goroutines in global queue
# - Local queues have goroutines spread across Psschedtrace shows scheduler state: how many processors are idle, how many threads are active, and how goroutines are distributed. High idleprocs with high runqueue means not enough Ps. High spinningthreads means the scheduler is looking for work.
http2debug
http2debug enables HTTP/2 debugging. It logs HTTP/2 frames, connection state, and flow control. Use it to diagnose HTTP/2 issues.
# Enable HTTP/2 debugging
GODEBUG=http2debug=1 ./myapp
# Output shows HTTP/2 frames:
# http2: Framer 0xc000123456: wrote HEADERS flags=END_STREAM stream=1 len=100
# http2: Framer 0xc000123456: wrote DATA flags=END_STREAM stream=1 len=500
# http2: Framer 0xc000123456: read HEADERS flags=END_STREAM stream=3 len=80
# http2: Framer 0xc000123456: read DATA flags=END_STREAM stream=3 len=200
# http2debug=2 shows more detail
GODEBUG=http2debug=2 ./myapphttp2debug=1 logs HTTP/2 frame operations. http2debug=2 adds connection-level details. Use this to diagnose HTTP/2 connection issues, flow control problems, and stream errors.
netdns
netdns controls DNS resolution behavior. It switches between the pure Go resolver and the cgo resolver, and enables DNS debugging.
# Use pure Go resolver (default on Linux)
GODEBUG=netdns=go ./myapp
# Use cgo resolver (system resolver)
GODEBUG=netdns=cgo ./myapp
# Automatic selection
GODEBUG=netdns=auto ./myapp
# Debug DNS resolution
GODEBUG=netdnsgo=1 ./myapp
# Check resolver in use
import "net"
fmt.Println(net.DefaultResolver PreferGo: true)netdns=go uses the pure Go resolver. netdns=cgo uses the system resolver via cgo. The pure Go resolver is faster and more predictable. The cgo resolver uses /etc/resolv.conf and supports advanced features.
Other Useful Flags
# Enable deadlock detection
GODEBUG=deadlock=1 ./myapp
# Enable memory sanitizer
GODEBUG=msan=1 ./myapp
# Disable cgo
CGO_ENABLED=0 ./myapp
# Set maximum OS threads
GOMAXPROCS=4 ./myapp
# Set maximum goroutines (deprecated, no limit)
# GOMAXGOROUTINES is not a real flag
# Enable race detector at runtime
# Use go build -race instead
# Disable TLS 1.3
GODEBUG=tls13=0 ./myapp
# Disable HTTP/2
GODEBUG=http2client=0 ./myapp
GODEBUG=http2server=0 ./myapp
# Enable verbose GC
GODEBUG=gctrace=1,gcpacertrace=1 ./myappGODEBUG provides many runtime diagnostics. deadlock=1 detects goroutine deadlocks. gcpacertrace=1 shows GC pacer details. These flags help diagnose issues without recompiling or adding instrumentation.
GODEBUG flags add overhead — use them in development and testing. In production, use them sparingly for diagnosis. gctrace=1 is low overhead and useful in production. schedtrace adds more overhead — use only when needed.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.