Home

Awesome

Go Timeouts

An unresponsive service can be worse than a down one. It can tie up your entire system if not handled properly. All network requests should have a timeout.

Here’s how to add timeouts for popular Go packages. All have been tested. The default is no timeout, unless otherwise specified. Enjoy!

Also available for Ruby, Python, Node, and Rust

Build Status

Packages

Standard library

github.com

Other

Standard Library

net

conn, err := net.DialTimeout(network, address, time.Second)
if err != nil {
    // handle error
}
err = conn.SetDeadline(time.Now().Add(time.Second))

net/http

client := http.Client{
    Timeout: time.Second,
}

net/smtp

conn, err := net.DialTimeout("tcp", address, time.Second)
if err != nil {
    // handle error
}
err = conn.SetDeadline(time.Now().Add(time.Second))
if err != nil {
    // handle error
}
client, err = smtp.NewClient(conn, host)

os/exec

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
err := exec.CommandContext(ctx, cmd).Run()

github.com

aws/aws-sdk-go

sess := session.Must(session.NewSession(&aws.Config{
    HTTPClient: &http.Client{Timeout: time.Second},
}))

aws/aws-sdk-go-v2

cfg, err := config.LoadDefaultConfig(context.TODO(),
    config.WithHTTPClient(&http.Client{Timeout: time.Second}),
)

bradfitz/gomemcache

mc := memcache.New(host)
mc.Timeout = time.Second

couchbase/gocb

cluster, err := gocb.Connect(connStr, gocb.ClusterOptions{
    TimeoutsConfig: gocb.TimeoutsConfig{
        ConnectTimeout:    time.Second,
        KVTimeout:         time.Second,
        ViewTimeout:       time.Second,
        QueryTimeout:      time.Second,
        AnalyticsTimeout:  time.Second,
        SearchTimeout:     time.Second,
        ManagementTimeout: time.Second,
    },
})

See the docs for defaults

elastic/go-elasticsearch

cfg := elasticsearch.Config{
    Transport: &http.Transport{
        DialContext: (&net.Dialer{
            Timeout: time.Second,
        }).DialContext,
        ResponseHeaderTimeout: time.Second,
    },
}
es, err := elasticsearch.NewClient(cfg)

emersion/go-smtp

conn, err := net.DialTimeout("tcp", address, time.Second)
if err != nil {
    // handle error
}
err = conn.SetDeadline(time.Now().Add(time.Second))
if err != nil {
    // handle error
}
client, err = smtp.NewClient(conn, host)

gocql/gocql

cluster := gocql.NewCluster(host)
cluster.ConnectTimeout = time.Second
cluster.Timeout = time.Second

Default: 600ms connect timeout, 600ms read timeout

go-pg/pg

db := pg.Connect(&pg.Options{
    DialTimeout:  time.Second,
    ReadTimeout:  time.Second,
    WriteTimeout: time.Second,
})

go-redis/redis

rdb := redis.NewClient(&redis.Options{
    DialTimeout:  time.Second,
    ReadTimeout:  time.Second,
    WriteTimeout: time.Second,
})

go-sql-driver/mysql

cfg := mysql.Config{
    Timeout:      time.Second,
    ReadTimeout:  time.Second,
    WriteTimeout: time.Second,
}
db, err := sql.Open("mysql", cfg.FormatDSN())

opensearch-project/opensearch-go

cfg := opensearch.Config{
    Transport: &http.Transport{
        DialContext: (&net.Dialer{
            Timeout: time.Second,
        }).DialContext,
        ResponseHeaderTimeout: time.Second,
    },
}
client, err := opensearch.NewClient(cfg)

Other

go.mongodb.org/mongo-driver/mongo

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))

Don’t see a library you use?

Let us know. Even better, create a pull request for it.

Running the Tests

git clone https://github.com/ankane/go-timeouts.git
cd go-timeouts
go mod tidy

To run all tests, use:

go test ./... -v

To run individual tests, use:

go test test/helper_test.go test/net_http_test.go -v