Around Go: MongoDB and Redis · 3 MIN READ

MongoDB: one client, explicit deadlines and typed documents

Connect with the Go v2 driver and separate construction, readiness, request work and cleanup.

MongoDB stores BSON documents and the Go driver manages discovery and pools for the deployment. A collection handle is not a new physical connection. Reuse a client across requests, model the fields the application owns, and keep network setup outside request-time package initialization.

Around Go: data stores · A MAP OF THE IDEA

  1. One shared client
  2. Bounded readiness
  3. Typed operation
  4. Bounded cleanup

Useful when

  • Connect with the Go v2 driver and separate construction, readiness, request work and cleanup.

Watch out

  • Connect configures a client; a bounded Ping separately tests current server readiness. Neither promises that future network operations cannot fail or time out.

Implementation & operation cost: One shared client owns pools and topology monitoring; each additional service instance multiplies that connection demand.

01

Construct the client and probe readiness

The example uses go.mongodb.org/mongo-driver/v2, with v2.3.1 as a reproducible example pin. Connect constructs the client; a successful Ping is separate evidence that a server is reachable. In a native development checkout, obtain the URI from configuration and use the deployment’s required authentication and TLS.

go
client, err := mongo.Connect(options.Client().ApplyURI(uri).SetMaxPoolSize(16))
if err != nil { return err }
probe, cancel := context.WithTimeout(ctx, 2*time.Second)
err = client.Ping(probe, readpref.Primary())
cancel()
if err != nil {
    cleanup, stop := context.WithTimeout(context.Background(), time.Second)
    defer stop()
    _ = client.Disconnect(cleanup)
    return err
}
Read the code

The fragment belongs to a startup function returning error and imports context, time, mongo, mongo/options and mongo/readpref from the v2 driver. The pool size is illustrative, not a production sizing recommendation.

02

Decode into a deliberate schema

Use BSON tags and explicit field types instead of letting every layer pass an unstructured map. Validate external input before constructing a query. ErrNoDocuments is an expected absence case when the contract allows it; it is different from a timeout, authorization failure or decode error.

go
type Note struct {
    ID bson.ObjectID `bson:"_id,omitempty"`
    Tenant string `bson:"tenant"`
    Body string `bson:"body"`
}
var note Note
err := notes.FindOne(ctx, bson.D{{Key: "tenant", Value: tenant}, {Key: "_id", Value: id}}).Decode(&note)
if errors.Is(err, mongo.ErrNoDocuments) { return ErrNotFound }
if err != nil { return fmt.Errorf("load note: %w", err) }
Read the code

notes is a collection from the shared client; tenant and id come from validated application inputs. The application defines ErrNotFound. An omitted tenant predicate could become a data-isolation bug even if the database query is fast.

03

Use separate lifetimes

Every request operation should inherit a bounded caller context. Startup probes and final Disconnect need their own lifetimes; do not reuse an already canceled request context for cleanup. These native service snippets are reading material: GopherForge does not add remote MongoDB sockets to its WASI execution sandbox.

TAKE THIS WITH YOU

Reuse a configured v2 client, prove readiness separately, decode explicit BSON models and distinguish absence from infrastructure failures.

Check your understanding

What does a successful mongo.Connect call establish?

Go to the source

Progress stays in this browser. No account needed.