Skip to main content
The latest major version of the algoliasearch-client-go package is version 4. This page helps you upgrade from version 3 and explains the breaking changes you need to address. Algolia generates the version 4 clients from OpenAPI specifications, which provides consistent behavior across all languages and up-to-date API coverage. The main architectural change is the removal of the InitIndex pattern: all methods are now on the client instance directly, with indexName as a parameter. For the full list of changes, see the Go changelog.

Update your dependencies

Update the algoliasearch-client-go package to version 4:
Command line
go get github.com/algolia/algoliasearch-client-go/v4

Update imports

The import path changed from v3 to v4:
Go
// version 3
import "github.com/algolia/algoliasearch-client-go/v3/algolia/search"

// version 4
import "github.com/algolia/algoliasearch-client-go/v4/algolia/search"

Update client initialization

In version 3, NewClient returned a client directly. In version 4, it returns a (client, error) pair, so you need to handle the error:
Go
// version 3
client := search.NewClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")

// version 4
client, err := search.NewClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
if err != nil {
  panic(err)
}

Understand the new API surface

Version 4 introduces two major changes to the API surface:
  • No more InitIndex. Version 3 relied on an index object with methods called on it. In version 4, all methods belong to the client instance, with indexName as a parameter.
  • Builder pattern for requests. Version 4 introduces typed request builders (NewApi*Request constructors) with With* methods for optional parameters.
The builder pattern is more verbose than version 3’s flat function signatures. The tradeoff is strong typing, better IDE autocompletion, and predictable structure that works well with AI coding assistants.
Go
// version 3
client := search.NewClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
index := client.InitIndex("INDEX_NAME")
index.Search("QUERY")

// version 4
client, err := search.NewClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
if err != nil {
  panic(err)
}
response, err := client.SearchSingleIndex(client.NewApiSearchSingleIndexRequest(
  "INDEX_NAME").WithSearchParams(
    search.SearchParamsObjectAsSearchParams(
      search.NewEmptySearchParamsObject().SetQuery("QUERY"))))
If you have many files to update, search your codebase for InitIndex or .InitIndex( to find every place that needs changing.

Update search calls

Search a single index

The index.Search() method is now client.SearchSingleIndex(). Build the request with NewApiSearchSingleIndexRequest and attach search parameters with WithSearchParams:
Go
// version 3
index := client.InitIndex("INDEX_NAME")
res, err := index.Search("QUERY", opt.Filters("category:Book"))

// version 4
response, err := client.SearchSingleIndex(client.NewApiSearchSingleIndexRequest(
  "INDEX_NAME").WithSearchParams(
    search.SearchParamsObjectAsSearchParams(
      search.NewEmptySearchParamsObject().
        SetQuery("QUERY").
        SetFacetFilters(search.ArrayOfFacetFiltersAsFacetFilters([]search.FacetFilters{*search.StringAsFacetFilters("category:Book")})))))

Search multiple indices

The client.MultipleQueries() method is now client.Search(). Each query in the request requires an IndexName:
Go
// version 3
res, err := client.MultipleQueries([]search.IndexedQuery{
  {IndexName: "INDEX_1", Params: search.Params{Query: search.Query("QUERY")}},
  {IndexName: "INDEX_2", Params: search.Params{Query: search.Query("QUERY")}},
})

// version 4
response, err := client.Search(client.NewApiSearchRequest(
  search.NewEmptySearchMethodParams().SetRequests(
    []search.SearchQuery{
      *search.SearchForHitsAsSearchQuery(
        search.NewEmptySearchForHits().SetIndexName("INDEX_1").SetQuery("QUERY")),
      *search.SearchForHitsAsSearchQuery(
        search.NewEmptySearchForHits().SetIndexName("INDEX_2").SetQuery("QUERY")),
    })))

Search for facet values

The index.SearchForFacetValues() method becomes client.SearchForFacetValues() with an indexName parameter:
Go
// version 3
index := client.InitIndex("INDEX_NAME")
res, err := index.SearchForFacetValues("category", "book", nil)

// version 4
response, err := client.SearchForFacetValues(client.NewApiSearchForFacetValuesRequest(
  "INDEX_NAME", "category"))

Update indexing operations

In version 4, indexing methods are on the client instead of the index object, with indexName as a parameter.

Add or replace records

Go
// version 3
index := client.InitIndex("INDEX_NAME")
res, err := index.SaveObject(map[string]any{"objectID": "1", "name": "Record"})

// version 4
response, err := client.SaveObject(client.NewApiSaveObjectRequest(
  "INDEX_NAME",
  map[string]any{
    "objectID": "1",
    "name":     "Record",
  }))

Partially update records

Go
// version 3
index := client.InitIndex("INDEX_NAME")
res, err := index.PartialUpdateObject(map[string]any{"objectID": "1", "name": "Updated"})

// version 4
response, err := client.PartialUpdateObject(client.NewApiPartialUpdateObjectRequest(
  "INDEX_NAME", "1", map[string]any{"name": "Updated"}))

Delete records

Go
// version 3
index := client.InitIndex("INDEX_NAME")
res, err := index.DeleteObject("1")

// version 4
response, err := client.DeleteObject(client.NewApiDeleteObjectRequest(
  "INDEX_NAME", "1"))

Update settings, synonyms, and rules

Get and set settings

Go
// version 3
index := client.InitIndex("INDEX_NAME")
settings, err := index.GetSettings()
index.SetSettings(search.Settings{SearchableAttributes: opt.SearchableAttributes("title", "author")})

// version 4
settingsResponse, err := client.GetSettings(client.NewApiGetSettingsRequest(
  "INDEX_NAME"))

setResponse, err := client.SetSettings(client.NewApiSetSettingsRequest(
  "INDEX_NAME",
  search.NewEmptyIndexSettings().
    SetSearchableAttributes([]string{"title", "author"})))

Save synonyms and rules

Go
// version 3
index := client.InitIndex("INDEX_NAME")
index.SaveSynonyms([]search.Synonym{{ObjectID: "1", Type: search.RegularSynonymType, Synonyms: []string{"car", "auto"}}})
index.SaveRules([]search.Rule{{ObjectID: "1", Conditions: []search.RuleCondition{{Anchoring: search.Contains, Pattern: "shoes"}}, Consequence: search.RuleConsequence{Params: &search.RuleParams{Query: search.NewRuleQueryObject(search.RuleQueryObjectParams{Edits: []search.QueryEdit{{Type: search.Remove, Delete: "shoes", Insert: "sneakers"}}})}}}})

// version 4
synonymResponse, err := client.SaveSynonyms(client.NewApiSaveSynonymsRequest(
  "INDEX_NAME",
  []search.SynonymHit{
    *search.NewEmptySynonymHit().SetObjectID("1").
      SetType(search.SynonymType("synonym")).
      SetSynonyms([]string{"car", "auto"}),
  }))

rulesResponse, err := client.SaveRules(client.NewApiSaveRulesRequest(
  "INDEX_NAME",
  []search.Rule{
    *search.NewEmptyRule().SetObjectID("1").
      SetConditions([]search.Condition{
        *search.NewEmptyCondition().SetPattern("shoes").SetAnchoring(search.Anchoring("contains")),
      }).
      SetConsequence(search.NewEmptyConsequence().SetParams(
        search.NewEmptyConsequenceParams().SetFilters("brand:sneakers"))),
  }))
In version 3, index.ReplaceAllRules() and index.ReplaceAllSynonyms() replaced all rules or synonyms. In version 4, use client.SaveRules() or client.SaveSynonyms() with the WithClearExistingRules(true) or WithReplaceExistingSynonyms(true) option on the request builder.

Update index management

The CopyIndex, MoveIndex, CopyRules, CopySynonyms, and CopySettings methods are all replaced by a single OperationIndex method.

Copy an index

Go
// version 3
client.CopyIndex("SOURCE_INDEX_NAME", "DESTINATION_INDEX_NAME")

// version 4
response, err := client.OperationIndex(client.NewApiOperationIndexRequest(
  "SOURCE_INDEX_NAME",
  search.NewEmptyOperationIndexParams().
    SetOperation(search.OperationType("copy")).
    SetDestination("DESTINATION_INDEX_NAME")))

Move (rename) an index

Go
// version 3
client.MoveIndex("SOURCE_INDEX_NAME", "DESTINATION_INDEX_NAME")

// version 4
response, err := client.OperationIndex(client.NewApiOperationIndexRequest(
  "SOURCE_INDEX_NAME",
  search.NewEmptyOperationIndexParams().
    SetOperation(search.OperationType("move")).
    SetDestination("DESTINATION_INDEX_NAME")))

Copy only rules or settings

In version 4, use the SetScope parameter to limit the operation to specific data:
Go
// version 4 -- copy only rules and settings from one index to another
response, err := client.OperationIndex(client.NewApiOperationIndexRequest(
  "SOURCE_INDEX_NAME",
  search.NewEmptyOperationIndexParams().
    SetOperation(search.OperationType("copy")).
    SetDestination("DESTINATION_INDEX_NAME").
    SetScope([]search.ScopeType{
      search.ScopeType("rules"),
      search.ScopeType("settings"),
    })))

Check if an index exists

In version 3, you could check if an index existed using the Exists method on the index object. In version 4, use the IndexExists helper method on the client:
Go
// version 3
index := client.InitIndex("INDEX_NAME")
ok, err := index.Exists()

// version 4
response, err := client.IndexExists("INDEX_NAME")

Update task handling

Version 3 supported chaining .Wait() on operations. Version 4 replaces this pattern with dedicated wait helpers.
Go
// version 3
index := client.InitIndex("INDEX_NAME")
res, err := index.SaveObjects(records)
res.Wait()

// version 4
response, err := client.SaveObjects("INDEX_NAME", records)
client.WaitForTask("INDEX_NAME", *response[0].TaskID)
Version 4 includes three wait helpers:

Helper method changes

The following sections document breaking changes in helper method signatures and behavior between version 3 and version 4.

ReplaceAllObjects

The opt.Safe() functional option has been removed. In version 3, passing opt.Safe(true) caused the helper to wait after each step. In version 4, the helper always waits—equivalent to the previous opt.Safe(true) behavior.
Go
// version 3
res, err := index.ReplaceAllObjects(objects, opt.Safe(true))

// version 4
res, err := client.ReplaceAllObjects(search.ReplaceAllObjectsParams{
    IndexName: "INDEX_NAME",
    Objects:   objects,
    Scopes:    []search.ScopeType{search.SCOPETYPE_SETTINGS, search.SCOPETYPE_RULES, search.SCOPETYPE_SYNONYMS},
})

SaveObjects

The opt.AutoGenerateObjectIDIfNotExist() functional option has been removed. In version 4, every object must include an ObjectID. To have the API generate object IDs, use ChunkedBatch with search.ACTION_ADD_OBJECT.
Go
// version 3
res, err := index.SaveObjects(objects, opt.AutoGenerateObjectIDIfNotExist(true))

// version 4
// Objects must include ObjectID, or use ChunkedBatch with ACTION_ADD_OBJECT
res, err := client.SaveObjects(search.SaveObjectsParams{
    IndexName: "INDEX_NAME",
    Objects:   objects,
})

PartialUpdateObjects

The opt.CreateIfNotExists() functional option has been replaced with an explicit field on the params struct. The default also changed: in version 3 it defaulted to false (used partialUpdateObjectNoCreate); in version 4 it defaults to true.
Go
// version 3
// Default: createIfNotExists = false
res, err := index.PartialUpdateObjects(objects, opt.CreateIfNotExists(true))

// version 4
// Default: createIfNotExists = true
res, err := client.PartialUpdateObjects(search.PartialUpdateObjectsParams{
    IndexName:         "INDEX_NAME",
    Objects:           objects,
    CreateIfNotExists: algoliaUtils.ToPtr(false), // explicitly set false to match old default
})

BrowseObjects, BrowseRules, BrowseSynonyms

The ObjectIterator, RuleIterator, and SynonymIterator types have been removed. These helpers now use an Aggregator callback that is called with each page of results.
Go
// version 3
it, err := index.BrowseObjects()
for {
    obj, err := it.Next()
    if err == io.EOF {
        break
    }
    process(obj)
}

// version 4
objects := []map[string]any{}

_, err := client.BrowseObjects(search.BrowseObjectsParams{
    IndexName: "INDEX_NAME",
    Aggregator: func(response *search.BrowseResponse) {
        objects = append(objects, response.Hits...)
    },
})

DeleteObjects

Two new optional parameters are available:
  • WithWaitForTasks(bool) (default false)
  • WithBatchSize(int) (default 1,000)
Go
// version 3
res, err := index.DeleteObjects([]string{"id1", "id2"})

// version 4
res, err := client.DeleteObjects("INDEX_NAME", []string{"id1", "id2"},
    search.WithDeleteObjectsWaitForTasks(true),
)

WaitForTask

The helper was renamed from WaitTask to WaitForTask, moved to the client, and now returns *GetTaskResponse instead of error. The timeToWait config option is replaced by explicit WithMaxRetries and WithTimeout options—the default timeout uses exponential backoff capped at 5 seconds.
Go
// version 3
err := index.WaitTask(taskID)

// version 4
resp, err := client.WaitForTask("INDEX_NAME", taskID)

// With explicit retry controls:
resp, err := client.WaitForTask("INDEX_NAME", taskID,
    search.WithWaitForTaskMaxRetries(50),
    search.WithWaitForTaskTimeout(func(count int) time.Duration {
        return min(time.Duration(count)*200*time.Millisecond, 5*time.Second)
    }),
)

WaitForAppTask

This is a new helper in version 4.
Go
resp, err := client.WaitForAppTask(taskID)

WaitForApiKey

This is a new standalone helper in version 4. In version 3, waiting for API key operations required polling GetAPIKey manually.
Go
// Wait for a key to be created:
resp, err := client.WaitForApiKey("my-api-key", search.APIKEYOPERATION_ADD, nil)

// Wait for a key update (pass the expected final state):
apiKey := &search.ApiKey{Acl: []search.Acl{search.ACL_SEARCH}}
resp, err := client.WaitForApiKey("my-api-key", search.APIKEYOPERATION_UPDATE,
    search.WithWaitForApiKeyApiKey(apiKey),
)

IndexExists

The helper was renamed from Exists() on the index object to IndexExists() on the client.
Go
// version 3
exists, err := index.Exists()

// version 4
exists, err := client.IndexExists("INDEX_NAME")

GenerateSecuredApiKey

The function moved from a package-level function to a method on the client and was renamed from GenerateSecuredAPIKey to GenerateSecuredApiKey. The restrictions are now a single typed struct instead of variadic functional options.
Go
// version 3
key, err := search.GenerateSecuredAPIKey("parentApiKey",
    opt.ValidUntil(1893456000),
    opt.RestrictIndices("INDEX_NAME"),
)

// version 4
key, err := client.GenerateSecuredApiKey("parentApiKey", &search.SecuredApiKeyRestrictions{
    ValidUntil:      algoliaUtils.ToPtr(int64(1893456000)),
    RestrictIndices: []string{"INDEX_NAME"},
})

GetSecuredApiKeyRemainingValidity

The method was renamed from GetSecuredAPIKeyRemainingValidity to GetSecuredApiKeyRemainingValidity. The variadic options parameter has been removed.
Go
// version 3
duration, err := client.GetSecuredAPIKeyRemainingValidity(key)

// version 4
duration, err := client.GetSecuredApiKeyRemainingValidity(key)

ChunkedBatch

ChunkedBatch is now a public helper. In version 3, chunking was an internal detail of SaveObjects. The action parameter is required.
Go
res, err := client.ChunkedBatch("INDEX_NAME", objects, search.ACTION_ADD_OBJECT,
    search.WithChunkedBatchWaitForTasks(true),
    search.WithChunkedBatchBatchSize(1000),
)

CopyIndexBetweenApplications

In version 3, the Account type provided a CopyIndex method for copying an index between two different Algolia applications. It accepted two *Index values, each carrying its own app credentials. In version 4, the Account type is removed. You can compose existing helpers across two clients to achieve the same result.
Go
// version 3
account := search.NewAccount(srcClient, destClient)
_, err := account.CopyIndex(srcIndex, destIndex)

// version 4
ctx := context.Background()
src, _ := search.NewClient("SRC_APP_ID", "SRC_API_KEY")
dst, _ := search.NewClient("DST_APP_ID", "DST_API_KEY")

// Copy settings
settings, _ := src.GetSettings(ctx, "SOURCE_INDEX")
dst.SetSettings(ctx, "DEST_INDEX", *settings)

// Copy rules
var rules []search.Rule
src.BrowseRules("SOURCE_INDEX", search.SearchRulesParams{},
    search.WithAggregator(func(res any, err error) {
        if r, ok := res.(*search.SearchRulesResponse); ok {
            rules = append(rules, r.Hits...)
        }
    }),
)
if len(rules) > 0 {
    dst.SaveRules(ctx, "DEST_INDEX", rules)
}

// Copy synonyms
var synonyms []search.SynonymHit
src.BrowseSynonyms("SOURCE_INDEX", search.SearchSynonymsParams{},
    search.WithAggregator(func(res any, err error) {
        if r, ok := res.(*search.SearchSynonymsResponse); ok {
            synonyms = append(synonyms, r.Hits...)
        }
    }),
)
if len(synonyms) > 0 {
    dst.SaveSynonyms(ctx, "DEST_INDEX", synonyms)
}

// Copy objects
var objects []map[string]any
src.BrowseObjects("SOURCE_INDEX", search.BrowseParamsObject{},
    search.WithAggregator(func(res any, err error) {
        if r, ok := res.(*search.BrowseResponse); ok {
            objects = append(objects, r.Hits...)
        }
    }),
)
dst.ReplaceAllObjects("DEST_INDEX", objects)

SaveObjectsWithTransformation

New in version 4. Routes objects through the Algolia Push connector. Requires the IngestionTransporter to be configured at client initialization via a region.
Go
res, err := client.SaveObjectsWithTransformation("INDEX_NAME", objects,
    search.WithChunkedBatchWaitForTasks(true),
    search.WithChunkedBatchBatchSize(1000),
)

ReplaceAllObjectsWithTransformation

New in version 4. Atomically replaces all objects via the Push connector (copy settings/rules/synonyms to a temp index → push objects → move back). Requires the IngestionTransporter to be configured at client initialization.
Go
res, err := client.ReplaceAllObjectsWithTransformation("INDEX_NAME", objects,
    search.WithReplaceAllObjectsBatchSize(1000),
    search.WithReplaceAllObjectsScopes([]search.ScopeType{
        search.SCOPETYPE_SETTINGS,
        search.SCOPETYPE_RULES,
        search.SCOPETYPE_SYNONYMS,
    }),
)

PartialUpdateObjectsWithTransformation

New in version 4. Routes partial updates through the Push connector. The createIfNotExists option defaults to false.
Go
res, err := client.PartialUpdateObjectsWithTransformation("INDEX_NAME", objects,
    search.WithPartialUpdateObjectsCreateIfNotExists(false),
    search.WithChunkedBatchWaitForTasks(false),
    search.WithChunkedBatchBatchSize(1000),
)

Method changes reference

The following tables list all method names that changed between version 3 and version 4.

Search API client

Version 3 (legacy)Version 4 (current)
client.AddAPIKeyclient.AddApiKey
client.AddAPIKey.waitclient.WaitForApiKey
client.ClearDictionaryEntriesclient.BatchDictionaryEntries
client.CopyIndexclient.OperationIndex
client.CopyRulesclient.OperationIndex
client.CopySynonymsclient.OperationIndex
client.DeleteAPIKeyclient.DeleteApiKey
client.DeleteDictionaryEntriesclient.BatchDictionaryEntries
client.GenerateSecuredAPIKeyclient.GenerateSecuredApiKey
client.GetAPIKeyclient.GetApiKey
client.GetSecuredAPIKeyRemainingValidityclient.GetSecuredApiKeyRemainingValidity
client.ListAPIKeysclient.ListApiKeys
client.ListIndicesclient.ListIndices
client.MoveIndexclient.OperationIndex
client.MultipleBatchclient.MultipleBatch
client.MultipleQueriesclient.Search
client.ReplaceDictionaryEntriesclient.BatchDictionaryEntries
client.RestoreAPIKeyclient.RestoreApiKey
client.SaveDictionaryEntriesclient.BatchDictionaryEntries
client.UpdateAPIKeyclient.UpdateApiKey
index.Batchclient.Batch
index.BrowseObjectsclient.BrowseObjects
index.BrowseRulesclient.BrowseRules
index.BrowseSynonymsclient.BrowseSynonyms
index.ClearObjectsclient.ClearObjects
index.ClearRulesclient.ClearRules
index.ClearSynonymsclient.ClearSynonyms
index.CopySettingsclient.OperationIndex
index.Deleteclient.DeleteIndex
index.DeleteByclient.DeleteBy
index.DeleteObjectclient.DeleteObject
index.DeleteObjectsclient.DeleteObjects
index.DeleteRuleclient.DeleteRule
index.DeleteSynonymclient.DeleteSynonym
index.Existsclient.IndexExists
index.FindObjectclient.SearchSingleIndex
index.GetObjectclient.GetObject
index.GetObjectsclient.GetObjects
index.GetRuleclient.GetRule
index.GetSettingsclient.GetSettings
index.GetSynonymclient.GetSynonym
index.GetStatusclient.GetTask
index.PartialUpdateObjectclient.PartialUpdateObject
index.PartialUpdateObjectsclient.PartialUpdateObjects
index.ReplaceAllObjectsclient.ReplaceAllObjects
index.ReplaceAllRulesclient.SaveRules
index.ReplaceAllSynonymsclient.SaveSynonyms
index.SaveObjectclient.SaveObject
index.SaveObjectsclient.SaveObjects
index.SaveRuleclient.SaveRule
index.SaveRulesclient.SaveRules
index.SaveSynonymclient.SaveSynonym
index.SaveSynonymsclient.SaveSynonyms
index.Searchclient.SearchSingleIndex
index.SearchForFacetValuesclient.SearchForFacetValues
index.SearchRulesclient.SearchRules
index.SearchSynonymsclient.SearchSynonyms
index.SetSettingsclient.SetSettings
index.{operation}.waitclient.WaitForTask

Recommend API client

Version 3 (legacy)Version 4 (current)
client.GetFrequentlyBoughtTogetherclient.GetRecommendations
client.GetRecommendationsclient.GetRecommendations
client.GetRelatedProductsclient.GetRecommendations
Last modified on April 22, 2026