github opensearch-project/opensearch-go v5.0.0

4 hours ago

opensearch-go v5.0.0

CRITICAL UPGRADE RELEASE NOTE - v5 is NOT a drop-in replacement for v4.

Two runtime defaults flip in v5, so code that compiles and passes against v4 can behave differently against v5 without a single line changing. Read this before you upgrade.

  1. Partial failures are now returned as errors. Bulk item failures, shard failures, and unconfirmed replica writes -- which v4 reported only inside the response body -- come back as typed Go error values by default (Config.Errors == nil now means errmask.Empty). Restore v4 behavior with Errors: errmask.New(errmask.All) or OPENSEARCH_GO_ERROR_MASK=all.
  2. The router is on by default. The client injects the default router and enables on-start node discovery unless OPENSEARCH_GO_ROUTER=false. In v4 this was opt-in.

Beyond the defaults, the module path changes to /v5, the opensearchapi package is now spec-generated (its Req/Resp/Params types are fully typed), the signer/aws (AWS SDK v1) package is removed, and several config fields and helpers are gone. The full field-level migration is in UPGRADING_V5.md and opensearchapi/UPGRADING_V4_TO_V5.md.

v5.0.0 is the first stable release of the v5 line. It ships the three themes the v4.7.x line previewed -- a partial-failure error model, a rewritten transport, and a topology-aware routing layer -- now as defaults, on top of an opensearchapi package generated in full from the OpenSearch API specification. The v4 line remains supported for callers who are not ready to move.

Requires Go 1.26 or later.

Full Changelog: v4.7.3...v5.0.0


1. Breaking changes in v5.0.0

Most surface at compile time. The upgrade guide has the complete list with before/after for each; these are the ones most likely to touch your code:

  • Module path is github.com/opensearch-project/opensearch-go/v5. Update your imports from /v4 to /v5; the in-source opensearchapi.X qualifier is unchanged.
  • Nested modules moved the major-version suffix to the end of the path, so .../opensearch-go/v5/osprom is now .../opensearch-go/osprom/v5 (and likewise osotel, log-slog, log-zerolog, cmd/osgen, cmd/osapilint). If you carried a replace directive to build these, delete it (#1115).
  • opensearchapi is now the code-generated package, replacing the hand-written v4 one (previewed in v4 at v5preview/opensearchapi/). Field-level deltas (DocumentID -> ID, optional Params becoming *Params, shared params moving into embedded TimeoutParams/DebugParams, BulkResp.Items becoming []BulkItem) are in opensearchapi/UPGRADING_V4_TO_V5.md (#650).
  • signer/aws is removed. Use signer/awsv2, which mirrors AWS's own SDK-version naming. For callers on v4 this is a full AWS SDK v1 -> v2 signer migration (session.Options -> aws.Config, and the OpenSearchService/OpenSearchServerless constants become the "es"/"aoss" literals).
  • opensearchtransport.DebuggingLogger and LoadDebugLogger() are removed, replaced by the new debuglog package. Set Config.DebugLogger (or OPENSEARCH_GO_LOG=debug) instead; adapters ship as the log-zerolog and log-slog modules (#828).
  • opensearchtransport.Client is renamed to opensearchtransport.Transport (#853).
  • EnableMetrics, IncludeDedicatedClusterManagers, and opensearch.ToPointer are removed. Per-request metrics are now always collected lock-free and Metrics() returns the full snapshot unconditionally; dedicated cluster managers are unconditionally excluded from request routing; replace ToPointer(v) with your own ptr helper or the native new(value) form (#892, #1004, #871).
  • Perform is removed from both opensearch.Client and opensearchtransport.Transport; Stream is now the sole method on opensearchtransport.Interface. Custom transports must implement Stream (#872).
  • Numeric query parameters are typed to match the spec: version params become *int so version=0 reaches the wire, and OpenAPI number params (min_score, requests_per_second, ...) become float64/*float64 (#1148, #1104).
  • Generated identifiers now follow Go initialism convention (IsmPolicy -> ISMPolicy, NodesInfoNode.Os -> OS, and many more); JSON wire tags are unchanged (#863).
  • The search response envelope is reshaped: resp.Hits is now SearchHitsMetadata and resp.Hits.Hits is []SearchHit, so _id, _score, _seq_no/_primary_term, and the sort cursor are reachable from a typed response for the first time. Access through resp.Hits.Hits[...] is unchanged.

2. Error handling (on by default in v5)

Partial failures that OpenSearch reports under an HTTP 200 -- failed bulk items, failed shards, unconfirmed replica writes -- are surfaced as typed Go errors:

Error type Returned by
*PartialBulkError Bulk
*PartialSearchError Search, MSearch, MSearchTemplate, SearchTemplate, Scroll.Get
*ShardFailureError Index, Doc.Create, Doc.Delete, Update
*MultiSearchItemError MSearch, MSearchTemplate (per sub-response)

Which categories are reported is a per-category mask on Config.Errors, overridable at runtime with OPENSEARCH_GO_ERROR_MASK. The recommended call-site pattern is a for/switch over opensearchapi.Errors(err), which flattens single- and multi-wrapper error shapes into one slice; on a partial failure the response is still fully populated alongside the error. Helpers IsPartialFailure, ToleratePartialFailures, and RequireSuccessRate support threshold-based tolerance. See guides/usage-error_handling.md (#816).

3. Routing (on by default in v5)

The client now chooses a node per request from cluster topology and load rather than plain round-robin, and auto-discovers nodes on start. OPENSEARCH_GO_ROUTER=false restores round-robin.

  • Role-aware: bulk/reindex/streaming route to ingest nodes; searches, mget, scroll, PIT, and field-caps to search/data nodes; writes and shard maintenance to data nodes. Dedicated cluster managers are excluded from request routing.
  • Shard-aware: client-side murmur3 hashing mirrors OpenSearch shard routing so ?routing= and document-ID requests reach a node hosting the target shard, with rendezvous-hashing fallback.
  • Congestion-aware: per-pool AIMD congestion windows, RTT bucketing that prefers AZ-local nodes and overflows under load, and thread-pool stats polling that demotes and recovers overloaded nodes.
  • Adaptive max_concurrent_shard_requests derived from a cluster-wide congestion signal, clamped to a [floor, cap] range, never applied over an explicit caller value.
  • Seed-URL fallback when all router pools are exhausted, triggering rediscovery. Disable with OPENSEARCH_GO_FALLBACK=false.

On a secured cluster the router's probes need read-only monitoring privileges (cluster:monitor/nodes, cluster:monitor/health); without them the client degrades gracefully to GET / and seed URLs rather than erroring. Full reference in guides/transport-routing.md and guides/config-envvars.md (#786, #816).

4. Generated API (opensearchapi)

The opensearchapi/ package is produced by cmd/osgen from the OpenAPI spec: consistent Req/Resp/Params triples, sub-clients mirroring OpenSearch namespaces (client.Cat, client.Cluster, client.Indices, ...), and a plugins/ subtree for ML, k-NN, security, ISM, and the rest.

  • Typed path builders in internal/path/ reject empty required segments, fixing a class of double-slash URL bugs across 74 request methods.
  • Enum-like oneOf-of-const schemas emit named Go string types with one exported const per value (e.g. NodeRole), and int-backed enums emit closed-set types with a typed unknown-value error.
  • The generator honors the OpenAPI discriminator and typed unions (CommonMappingProperty, the analysis unions, ClusterRemoteInfoCluster) so 146 subtypes decode by the property the payload names rather than a token-class guess.
  • Union branch accessors return (T, error) instead of a silent zero value when the union holds a different branch (opensearchapi.UnionBranchError).
  • Backward-compatibility forwarders keep top-level client.Bulk/MGet/Update and the client.Document/client.PointInTime/client.Indices field aliases working during migration.

5. Transport, connection lifecycle, and observability

  • Client.Close() on opensearch.Client and opensearchapi.Client releases discovery, health/stats polling, and DNS-refresh goroutines along with idle connections. Implicitly-created default clients are cached and shared by config hash, tunable with OPENSEARCH_GO_DEFAULT_CLIENT_TTL (#893).
  • Native API-key auth via APIKey on opensearch.Config (sends Authorization: ApiKey <key>) (#907).
  • Client-side DNS caching, on by default, with last-known-good fallback through transient resolver outages.
  • InsecureSkipVerify disables TLS verification without a custom http.Transport, keeping pooling, HTTP/2, and timeout defaults.
  • Stream() for raw byte forwarding and per-attempt RequestTimeout to bound stalled round-trips.
  • Lock-free metrics and an enriched observer surface: RequestEvent gains RouteName/Index/PoolName, response and stream events fire per request, and the osprom and osotel modules provide Prometheus and OpenTelemetry metric bundles off the core dependency graph.
  • Data-race and correctness fixes on the retry path (request mutation across attempts, HTTP/2 connection reuse after timeout, base-path stacking on retries) and HTTP/2 repair when CACert/InsecureSkipVerify is set on a caller-supplied transport (#1121, #1089, #1162).

6. Bulk indexer

  • Flush(context.Context) error on the opensearchutil.BulkIndexer interface drains the queue on demand and leaves the indexer open. Types implementing the interface must add the method (#336).
  • Per-document ordering: every action on one document routes to a fixed worker so a create and a follow-up update flush in order (#464).
  • Correctness fixes: _id/routing values are no longer HTML-escaped before transmission (a data-corruption bug present since 2021), mixed bulk batches route per-item rejections correctly to OnError/OnFailure, and peak batch memory is released after a traffic burst subsides (#824, #1106, #912).

7. Tooling

  • cmd/osgen generates the opensearchapi package and typed path builders from the spec, with checked-in allowlists guarding json.RawMessage and duplicate-JSON-tag shadowing so a generator regression fails generation rather than silently widening the raw-JSON surface.
  • cmd/osapilint migrates a Go module across major versions: rewrite applies syntactic API-shape changes before the code compiles against the target, and vet -fix catches runtime type-assertion hazards. Ships the v2 -> v3, v3 -> v4, and v4 -> v5 hops, chainable to migrate v2 -> v5 (#933, #951).

Dependencies

  • Bump golangci-lint v2.11.2 -> v2.11.4.
  • Bump github.com/aws/aws-sdk-go-v2 v1.41.1 -> v1.41.7, .../config -> v1.32.17, .../credentials -> v1.19.16, and github.com/aws/smithy-go v1.24.0 -> v1.25.1 (#831).
  • Bump golang.org/x/sync v0.19.0 -> v0.20.0, golang.org/x/mod v0.33.0 -> v0.35.0, and github.com/wI2L/jsondiff v0.7.0 -> v0.7.1 (#831).

Upgrade guides and documentation

  • UPGRADING.md - version-history index across every major version
  • UPGRADING_V5.md - v4 -> v5 migration, with before/after for each breaking change
  • opensearchapi/UPGRADING_V4_TO_V5.md - field-level delta for the generated API package, including the union rename table
  • guides/README.md - index of all guides, grouped by subsystem
  • guides/usage-error_handling.md - partial-failure errors and the error-mask reference
  • guides/transport-routing.md - routing architecture, connection scoring, pool lifecycle, and cost model
  • guides/transport-node_discovery_and_roles.md - node discovery and role-based selection
  • guides/transport-cluster_health_checking.md - health-check capability detection and the cluster:monitor permissions the router needs on a secured cluster
  • guides/transport-metrics.md - client-side metrics and connection/policy/router snapshots
  • guides/transport-observer_metrics.md - the observer event sink behind the osprom and osotel modules
  • guides/config-envvars.md - canonical reference for every OPENSEARCH_GO_* environment variable
  • USER_GUIDE.md - general usage and AWS signer setup
  • CHANGELOG.md - the complete, unabridged list of changes in this release

Contributors

Thanks to everyone who contributed to this release: @ryanyuan, @sean-, @iprithv, @magic-peach, @Ashwinnbr007, @peterzhuamazon, @Hailong-am, @iamrajiv, @Jakob3xD, @jeffmclean-cs, @LeeFred3042U, @MohammedAlkindi, @molloyzak13, @sooncj, @typhon8, @venkateshwaracholan, and @yanaix10.

New Contributors

Don't miss a new opensearch-go release

NewReleases is sending notifications on new releases.