# Meilisearch Search for GoCommerce — Open-Source Module

> Typo-tolerant product search for a GoCommerce store: a worker keeps a Meilisearch index in step with the catalogue, and the store proxies the searches.

- Canonical: https://kitcommerce.store/integrations/search-meilisearch/
- Last updated: 2026-09-25

---

Search

## Meilisearch product search for GoCommerce

A Go package that keeps a Meilisearch index of the catalogue and answers storefront searches from it. A worker pushes what changed every 30 seconds, an operator can rebuild the index from the admin, and the storefront searches through the store without holding a key of its own.

- **Search** module
- **6** settings
- **2** tests
- **3** API operations
- **ext/search-meilisearch**

### What it does

In the package’s own words it is “the sync and the door”: a worker walks the catalogue and pushes what changed, an operator can ask for a full rebuild, and the storefront searches through the store rather than holding a key — though the search-only key is published for a storefront that wants to talk to Meilisearch directly.

Each active product becomes one document: title, plain-text description, vendor, product type, tags, category, picture, SKUs, option values, the cheapest and dearest active variant, whether anything is in stock, and when it last changed. On a full sync the module creates the index if it is missing and sets what is searched, filtered and sorted on.

It talks to Meilisearch over Go’s standard library — indexing is one POST of a JSON array, searching one POST of a query — and it is configured from the Plugins screen, or from Config for a store that prefers environment variables. Where both say something, the screen wins.

### Configuration

Two settings are required: where Meilisearch is, and a key that may write to it. Set them in Config, hand them to the reference binary’s -meilisearch flag through the environment, or type them on the Plugins screen.

*Meilisearch module settings — 6 settings, 2 required*

| Setting | Environment variable | Required | What it does |
| --- | --- | --- | --- |
| `Host` Meilisearch URL | `MEILI_HOST` | Yes | The Meilisearch address — http://127.0.0.1:7700, or a cloud address. Marked public, so the panel’s value is handed to the storefront through GET /api/plugins. |
| `APIKey` API key | `MEILI_API_KEY` | Yes | A key allowed to write the index: the master key on a laptop, an admin key in production. The package doc’s example reads it from MEILI_MASTER_KEY; the reference binary reads MEILI_API_KEY. |
| `SearchKey` Search-only key | `MEILI_SEARCH_KEY` | No | A search-only key the storefront may hold. The store’s own search route uses it when set, and the API key when not. |
| `Index` Index name | — | No | The index to write and search, products by default. Set it on the Plugins screen: the panel field’s own default stands in front of Config, so Config.Index is never read. |
| `Poll` | — | No | How often the worker looks for changed products: 30 seconds when zero, and a negative value turns the worker off for a store that calls Sync itself. Go only. |
| `Client` | — | No | Replaces the HTTP client, which otherwise times out after 30 seconds. Go only. |

The module reads its Config struct, not the environment. The variable names are the ones the package’s own example or the reference binary uses; in your own `main()` you choose where each value comes from. Where a setting has a panel label, the admin’s settings drawer can hold it too, and a value typed there wins over Config.

### Setting it up

1. **Run Meilisearch** — Beside your database, or as a hosted instance. Note its URL and a key that may write indexes, and a search-only key if the storefront will query it directly.
2. **Install the module** — Pass meilisearch.New to gocommerce.New, as below — or start the reference binary with -meilisearch, which reads MEILI_HOST, MEILI_API_KEY and MEILI_SEARCH_KEY.
3. **Switch it on** — With a host and key in Config it starts switched on. Otherwise enable Meilisearch on the Plugins screen and fill in the URL and key there.
4. **Search** — The first poll is a full sync. The storefront calls GET /x/meilisearch/search?q=… with optional limit, offset, filter and sort, and gets Meilisearch’s hits back.

main.go

```
import (
	"os"

	"github.com/itswadesh/gocommerce/core"
	meilisearch "github.com/itswadesh/gocommerce/ext/search-meilisearch"
)

app, err := gocommerce.New(cfg, meilisearch.New(meilisearch.Config{
	Host:      os.Getenv("MEILI_HOST"),
	APIKey:    os.Getenv("MEILI_API_KEY"),
	SearchKey: os.Getenv("MEILI_SEARCH_KEY"),
}))
```

The package doc’s example with its imports, using the variable names the reference binary reads — the doc itself reads the write key from MEILI_MASTER_KEY. cfg is your gocommerce.Config. Import path `github.com/itswadesh/gocommerce/ext/search-meilisearch`.

### How it works

- **A worker, not a hook**

  Every 30 seconds the worker sends the products whose updated_at is newer than the last sync. The first poll after start, and every twentieth after that, is a full pass that also removes what the catalogue no longer holds.

- **Archived means removed**

  A product that is no longer active is deleted from the index on the next pass, so a draft or archived product stops appearing in results without a rebuild.

- **Rebuild from the admin**

  POST /api/admin/x/meilisearch/reindex runs a full sync on demand. GET /api/admin/x/meilisearch/status reports whether the index is on, configured and in step, with counts and the last error.

- **A search route with no key**

  GET /x/meilisearch/search takes q, limit (up to 100, 20 by default), offset, filter and sort, queries with the search-only key or the API key, and returns hits, total and processing time. It answers 404 while search is off.

- **Index settings, set for you**

  A full sync creates the index with id as its primary key and sets searchable attributes (title first, then SKUs, vendor, type, tags, category, options, description), filters and sorts on price, stock, category and the rest.

- **One sync at a time**

  A sync asked for while another runs in the same process is refused with “a sync is already running” — the reindex route answers 409 — rather than overlapping it.

### What it does not do

Read these before an order depends on it. No store is known to run GoCommerce in production yet, so these come from the code, not from anyone’s experience.

- **Variant edits wait for a full pass** — The incremental pass picks products by their own updated_at, and a price or stock change is written to the variant, not the product. It reaches the index at the next full pass — ten minutes at the defaults — or on a manual rebuild.
- **Sending is not indexing** — Meilisearch applies document writes as background tasks. The module sends them and does not wait for those tasks, so the indexed count on the status route is a count of documents sent.
- **State lives in the process** — The last sync time and the counts are held in memory: a restart forgets them, and its first poll is a full sync. Several instances each run a worker and push the same documents.
- **The default language only** — Documents hold the catalogue’s stored copy. Text from the translations module is not indexed, so a French shopper searches the default language.
- **Config values are not published** — Host and search key reach the storefront through GET /api/plugins only when typed into the panel. Values set in Config are used by the store but not handed out.
- **Config.Index is ignored** — The panel’s index field has a default of its own, and the module reads the panel first — so an index name set only in Config never takes effect. Name the index on the Plugins screen.
- **Five query parameters** — The search route passes q, limit, offset, filter and sort, and nothing else — facet counts and highlighting mean querying Meilisearch directly with the search-only key.

FAQ

### Questions about the Meilisearch module

**Does the storefront need a Meilisearch key?**

No. GET /x/meilisearch/search sends the query through the store, using the search-only key or, when there is none, the API key. A storefront that would rather query Meilisearch directly can use the search-only key, which the Plugins screen publishes when it is typed there.

**How quickly does a change show up in search?**

A change to a product itself goes out on the next poll, 30 seconds by default. A change to a variant’s price or stock waits for the next full pass — every twentieth poll, ten minutes at the defaults — or for a rebuild from the admin.

**What does a store without it get?**

GET /api/products?q= in the core matches a substring of a product’s title or description: no typo tolerance, no ranking, no filters beyond the listing’s own. This module is what adds a search engine; leave it out and none of its code is in your binary.

**Does Svelte Commerce search through it?**

Not yet. Svelte Commerce’s GoCommerce connector, version 0.1.0, covers catalogue, cart, checkout and order lookup, not a search index. A storefront you write against the API can call the search route directly.

**Is this a Meilisearch partnership?**

No. The module calls Meilisearch’s public API on an instance you run or rent. Meilisearch does not endorse GoCommerce, and no store is known to run this module in production yet.

### Source

Everything on this page is read from [`ext/search-meilisearch`](https://github.com/itswadesh/gocommerce/tree/main/ext/search-meilisearch) in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.Meilisearch is a trademark of its owner; this module talks to its public API and implies no endorsement. See [trademarks](https://kitcommerce.store/about/#trademarks).

- [ext/search-meilisearch on GitHub](https://github.com/itswadesh/gocommerce/tree/main/ext/search-meilisearch)
- [Meilisearch](https://www.meilisearch.com)
- [All GoCommerce modules](https://kitcommerce.store/integrations/)

### Try it against a store of your own

The one-command stack gives you GoCommerce’s API and admin on your own machine in minutes. Add this module to it and try it on test orders before a real one depends on it.

[Deploy in minutes](https://kitcommerce.store/#one-command) · [Read the module](https://github.com/itswadesh/gocommerce/tree/main/ext/search-meilisearch) · [All integrations](https://kitcommerce.store/integrations/)
