In this article, let's take a look at some of the most significant changes in Meilisearch's latest update. You can read the full changelog on GitHub, but we’ll go over the main ones in this article.

Zero downtime index deployment

Syncing your database changes with your Meilisearch index results in downtime. You cannot afford a “broken” search: user experience is paramount. You’ve come up with some workaround, but it takes time and resources. There must be a simpler way to handle this, right?

v0.30 introduces index swapping. You can now deploy a new index version with zero downtime!

To synchronize the changes between your primary database and your Meilisearch index  —indexA— in production, you just need to take the following steps:

  • Step 1: Create a new version of the index —indexA_new— containing all those changes
  • Step 2: Swap indexes, which means you replace the documents, settings, and task history of indexA with those of indexA_new. This is the request you need to send for the magic to happen:
curl \
  -X POST 'http://localhost:7700/swap-indexes'\
  -H 'Content-Type: application/json' \
  --data-binary '[
      { "indexes": ["indexA", "indexA_new"] }

⏲️ Wait for the task’ status to update to succeeded...

🎉 Tada! Your changes are now in production! Your users are still searching in indexA, but it holds the data of indexA_new now, and indexA_new holds the data of indexA.

New features: task cancelation and deletion

v0.30 gives you more control over asynchronous operations: you can now cancel tasks and delete your task history.

Task cancelation

The inability to cancel tasks has been one of the recurring problems users have raised over time. Not being able to interrupt tasks enqueued by mistake or taking too long to process can be very frustrating.

With v0.30, this problem is now a thing of the past. With the new API route /tasks/cancel, you can cancel enqueued or processing tasks based on their:

  • uid
  • status
  • type
  • indexUid
  • the date they were enqueued or started (beforeEnqueuedAt, afterEnqueuedAt, beforeStartedAt, afterStartedAt)

You can learn more about tasks in our documentation.

To cancel all enqueued tasks that add or update documents to an index, you should send the following request:

curl \
  -X POST 'http://localhost:7700/tasks/cancel?statuses=enqueued&types=documentAdditionOrUpdate’

Task deletion

Succeeded or failed —and now canceled— task information can take up much-needed disk space in instances with a large number of asynchronous operations. Clean up finished tasks with the new DELETE /tasks endpoint.

Just as for task cancelation, task deletion can be done based on the tasks’:

  • uid
  • status
  • type
  • indexUid
  • the date they were enqueued or started (beforeEnqueuedAt, afterEnqueuedAt, beforeStartedAt, afterStartedAt)

But you can also delete them based on the date they finished processing and what task canceled them:

  • beforeFinishedAt
  • afterFinishedAt
  • canceledBy

The following request deletes all tasks processed before October 11, 2020, at 11:49:53 am.

curl \
  -X DELETE 'http://localhost:7700/tasks?beforeFinishedAt=2020-10-11T11:49:53.000Z'

New feature: configuration file support

Thanks to our dear contributor mlemesle, a new way of configuring your Meilisearch instance has entered the chat. Along with environment variables and CLI options, you can use a configuration file 🥳

Configuration files can be easily shared and versioned. They allow you to manage all configuration options in one place and give an overall view at a glance.

To do so, set the desired instance options in a single  .toml  file:

env = "production"
master_key = "YOUR_MASTER_KEY_VALUE"

You can use the --config-file-path CLI option or the MEILI_CONFIG_FILE_PATH environment variable to specify a configuration file. Otherwise, Meilisearch will use the file ./config.toml in the working directory as the default configuration file. You can download a default configuration file with the following command:

curl > config.toml
Please note that specifying the config-file-path key in the configuration file will throw an error.

If no configuration file is provided, the Config file path is set to none.

Improvement: search result pagination

v0.30 introduces a numbered pagination mode for users who need pagination interfaces.

Up to v0.29, when using the search endpoint, Meilisearch only returned estimatedTotalHits, an estimate of how many documents matched the query. For this reason, creating interfaces with a page selector was not recommended.

You can now use the new search parameters page or hitsPerPage to get the exhaustive number of hits and the total number of pages for a query.

curl \
  -X POST 'http://localhost:7700/indexes/movies/search' \
  -H 'Content-Type: application/json' \
  --data-binary '{ "q": "american ninja", "page": 1 }'

The above request will fetch the first page of results for the given query and will return the following response:

  "hits": [
        // … 20 hits
  "query": "american ninja",
  "processingTimeMs": 2,
  "hitsPerPage": 20,
  "page": 1,
  "totalPages": 49,
  "totalHits": 966

As you can see, it returns the exhaustive number of search results (totalHits) and the number of search results pages (totalPages), which allows you to create numbered pagination interfaces easily.

👉 Note that totalHits and totalPages are calculated based on the pagination.maxTotalHits index setting.

Breaking changes

Field rename

When deleting documents by batch, the corresponding task object contains a field with the number of document ids received. This field, previously called receivedDocumentIds, has been renamed to providedIds.

New error

In cases where users try accessing the /keys route without setting a master key, Meilisearch now throws a more helpful error  missing_master_key:

    "message": "Meilisearch is running without a master key. To access this API endpoint, you must have set a master key at launch.",
    "code": "missing_master_key",
    "type": "auth",
    "link": ""

Task filter and error naming

To keep naming consistent with the value they can have, we have pluralized the query parameters used to filter tasks:

  • indexUid becomes indexUids
  • type becomes  types
  • status becomes  statuses

We have also renamed the following error codes:

  • invalid_task_type to invalid_task_types_filter
  • invalid_task_status to invalid_task_statuses_filter

Hacktoberfest contributions

We are infinitely grateful for all the contributions we received during Hacktoberfest. Most of the changes mentioned above were from these contributions, and we would like to highlight two more. We would not have released them in this version if it were not for our contributors.

  • Support for compressed API requests (Gzip, Brotli, Zlib) by @mou
  • Apple Silicon binaries are available thanks to @jeertmans

Other changes

  • Meilisearch has been binding by default to , which is an IPv4 address. In order to make Meilisearch reachable through both IPv4 ( and IPv6 ([::1]:7700) addresses, we have changed the default address to localhost:7700.
  • All task objects now contain the canceledBy and error fields
  • New task filters are available for the GET /tasks endpoint:
    • uids
    • beforeEnqueuedAt / afterEnqueuedAt
    • beforeStartedAt / afterStartedAt
    • beforeFinishedAt / afterFinishedAt
    • canceledBy
  • We have introduced a new task type: snapshotCreation. Snapshots tasks are now visible in the task list
  • The indexing speed has been significantly increased
  • We have reduced both the size of the Meilisearch binary and the size the Meilisearch instance takes up in disk space
  • All instance options now have their corresponding environment variable. Some related to the snapshot and dump features were missing

A big thank you to all our contributors! This project wouldn't have gotten very far without your help 🙏

And that’s it for v0.30! Remember to check the changelog for the full release notes.