{"id":43317067,"url":"https://github.com/alchemaxinc/meilisearch-lambda-wrapper","last_synced_at":"2026-05-03T03:08:15.157Z","repository":{"id":335913951,"uuid":"1128553037","full_name":"alchemaxinc/meilisearch-lambda-wrapper","owner":"alchemaxinc","description":"A wrapper script to make Meilisearch operations synchronous for hosting on AWS Lambda.","archived":false,"fork":false,"pushed_at":"2026-04-05T00:54:45.000Z","size":6199,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-05T02:19:48.162Z","etag":null,"topics":["aws","efs","lambda","meilisearch"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alchemaxinc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-05T20:11:08.000Z","updated_at":"2026-04-05T00:51:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alchemaxinc/meilisearch-lambda-wrapper","commit_stats":null,"previous_names":["alchemaxinc/meilisearch-lambda-wrapper"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/alchemaxinc/meilisearch-lambda-wrapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alchemaxinc%2Fmeilisearch-lambda-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alchemaxinc%2Fmeilisearch-lambda-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alchemaxinc%2Fmeilisearch-lambda-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alchemaxinc%2Fmeilisearch-lambda-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alchemaxinc","download_url":"https://codeload.github.com/alchemaxinc/meilisearch-lambda-wrapper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alchemaxinc%2Fmeilisearch-lambda-wrapper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31702581,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T21:17:31.016Z","status":"online","status_checked_at":"2026-04-12T02:00:06.763Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","efs","lambda","meilisearch"],"created_at":"2026-02-01T22:06:11.433Z","updated_at":"2026-05-03T03:08:15.145Z","avatar_url":"https://github.com/alchemaxinc.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Meilisearch on AWS Lambda\n\n\u003e Run [Meilisearch](https://www.meilisearch.com/) on **AWS Lambda** as a serverless full-text search\n\u003e engine with **Amazon EFS**, **Lambda Web Adapter**, and synchronous writes.\n\n[![GitHub Release](https://img.shields.io/github/v/release/alchemaxinc/meilisearch-lambda-wrapper)](https://github.com/alchemaxinc/meilisearch-lambda-wrapper/releases)\n\nThis repository is a Meilisearch Lambda wrapper and Terraform example for self-hosting Meilisearch on\nAWS Lambda. It combines [Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter),\npersistent Amazon EFS storage, and a lightweight Rust proxy that waits for Meilisearch's asynchronous\nwrite tasks to complete before the Lambda invocation returns.\n\nIf you are looking for **serverless Meilisearch**, **Meilisearch on Lambda**, or a low-cost way to run\nMeilisearch on AWS without an always-on EC2/ECS host, this project is intended to be a practical\nstarting point.\n\n**Who is this for?** Developers and small teams looking for a low-cost, serverless alternative to\nMeilisearch Cloud, Algolia, or a dedicated EC2/ECS instance, especially for side projects,\ninternal tools, or low-to-moderate traffic workloads.\n\n## Quick start: deploy Meilisearch on AWS Lambda\n\nPre-built binaries for `x86_64` and `aarch64` are published on every\n[GitHub Release](https://github.com/alchemaxinc/meilisearch-lambda-wrapper/releases).\n\nCreate a `Dockerfile` for your Lambda function:\n\n```dockerfile\nFROM alpine:3.21 AS fetcher\n\nARG TARGETARCH\nARG WRAPPER_VERSION=2.0.4\n\nRUN apk add --no-cache curl \u0026\u0026 \\\n    case \"${TARGETARCH}\" in \\\n      amd64) RUST_TARGET=\"x86_64-unknown-linux-musl\" ;; \\\n      arm64) RUST_TARGET=\"aarch64-unknown-linux-musl\" ;; \\\n      *) echo \"Unsupported architecture: ${TARGETARCH}\" \u0026\u0026 exit 1 ;; \\\n    esac \u0026\u0026 \\\n    curl -fsSL -o /wrapper \\\n      \"https://github.com/alchemaxinc/meilisearch-lambda-wrapper/releases/download/v${WRAPPER_VERSION}/wrapper-${RUST_TARGET}\" \u0026\u0026 \\\n    chmod +x /wrapper\n\nFROM getmeili/meilisearch:v1.42.1\n\nWORKDIR /app\n\nCOPY --from=fetcher /wrapper ./wrapper\nCOPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:1.0.0 /lambda-adapter /opt/extensions/lambda-adapter\n\nENTRYPOINT [\"/app/wrapper\"]\n```\n\nPin the wrapper version with a build arg:\n\n```sh\ndocker build --build-arg WRAPPER_VERSION=1.2.3 .\n```\n\n### Verifying checksums\n\nEach release includes `.sha256` files per binary:\n\n```sh\ncurl -fsSL -O https://github.com/alchemaxinc/meilisearch-lambda-wrapper/releases/download/v2.0.4/wrapper-x86_64-unknown-linux-musl{,.sha256}\nsha256sum -c wrapper-x86_64-unknown-linux-musl.sha256\n```\n\n### Minimum deployment requirements\n\n- An **AWS Lambda** function using a **container image**\n- **[Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter)** (`AWS_LWA_PORT=8080`)\n- An **Amazon EFS** file system mounted to the Lambda for persistent index storage\n- Meilisearch data directories (`/data`, `/dump`, `/snapshots`) pointing at the EFS mount\n- A **master key** passed via the `MEILI_MASTER_KEY` environment variable\n\nAn example Terraform setup covering all of the above is available in the\n[`docs/terraform_example/`](docs/terraform_example/README.md) folder.\n\n## Architecture\n\n```mermaid\nflowchart LR\n    Request((\"Client\u003cbr/\u003eRequest\")) --\u003e|HTTP| Gateway[\"AWS API\u003cbr/\u003eGateway\"]\n    Gateway --\u003e Wrapper\n\n    subgraph Lambda[\"AWS Lambda\"]\n        subgraph Docker[\"Docker Container\"]\n            Wrapper[\"wrapper\"] --\u003e|\"1: Forward\u003cbr/\u003erequest\"| Meili[\"getmeili/meilisearch\"]\n            Meili -.-\u003e|\"2: Poll until\u003cbr/\u003ecomplete (or\u003cbr/\u003eLambda timeout)\"| Wrapper\n        end\n    end\n\n    Meili \u003c--\u003e|\"Persistent\u003cbr/\u003estorage\"| EFS[(\"EFS\u003cbr/\u003e/data\u003cbr/\u003e/dump\u003cbr/\u003e/snapshots\")]\n```\n\n## Can Meilisearch run on AWS Lambda?\n\nYes — but not out of the box. Meilisearch is primarily\n[asynchronous](https://www.meilisearch.com/docs/learn/async/asynchronous_operations): write\noperations (adding documents, updating settings, creating indexes) return a task ID immediately\nand process the work in a background queue. On a traditional server, this is fine — the process\nstays alive. On AWS Lambda, the function may be frozen or terminated before Meilisearch finishes\nprocessing the queued task. Read operations (search queries) work fine, but writes will silently\nfail.\n\nSimply placing Meilisearch behind the\n[Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) is **not enough** to\nsolve this. The adapter handles HTTP routing, but does nothing about the async write gap.\n\nThis wrapper solves the problem by sitting between the Lambda Web Adapter and Meilisearch,\nintercepting `POST` requests to `/indexes/*` (document additions, setting updates, etc.),\nforwarding them to Meilisearch, and then **polling the task endpoint until the operation\ncompletes** before returning the response. The Lambda invocation stays alive for exactly as long\nas the write needs.\n\nAll other requests — searches, GETs, DELETEs — are proxied through untouched with minimal overhead.\n\n### How this differs from basic Meilisearch Lambda examples\n\nMany Meilisearch on AWS Lambda examples show that Meilisearch can start behind Lambda Web Adapter and\nread indexes from EFS. That is enough for search-only demos, but it does not address Meilisearch's\nasynchronous write queue.\n\n| Approach                              | What works                           | What is missing                         |\n| ------------------------------------- | ------------------------------------ | --------------------------------------- |\n| Meilisearch + Lambda Web Adapter only | HTTP routing and read/search traffic | Reliable document and settings writes   |\n| Meilisearch + Lambda + EFS only       | Persistent index storage             | Waiting for async Meilisearch tasks     |\n| This Meilisearch Lambda wrapper + EFS | Reads, writes, persistence, IaC      | Not intended for high-traffic workloads |\n\n## Why serverless Meilisearch?\n\nRunning a full-text search engine typically means paying for an always-on server or a managed\nservice. For many use cases that's overkill:\n\n- **Side projects and portfolios** that get a handful of searches a day\n- **Internal tools** used during business hours only\n- **Staging environments** that sit idle most of the time\n- **Prototyping** where you want instant full-text search without committing to infrastructure\n\nAWS Lambda's generous free tier (1 million requests/month) combined with EFS for persistent\nstorage makes it possible to run a self-hosted Meilisearch instance for **near-zero cost** at\nlow traffic volumes, scaling up automatically when needed.\n\n## How the wrapper works\n\nThe wrapper is a small, fast Rust binary (~3 MB)\nthat runs as the container's entrypoint. On startup it:\n\n1. **Launches Meilisearch** as a child process (listening on `localhost:7700`)\n2. **Starts an HTTP proxy** on port `8080` (where Lambda Web Adapter forwards traffic)\n3. **Proxies all requests** to Meilisearch, with special handling for index writes:\n   - Intercepts `POST /indexes/*` requests\n   - Forwards the request to Meilisearch and captures the returned `taskUid`\n   - Polls `GET /tasks/{taskUid}` until the task reaches a terminal state (`succeeded`, `failed`,\n     or `canceled`)\n   - Returns the final task result synchronously to the caller\n\nThis means your application code doesn't need to change — just point it at the Lambda URL instead\nof a Meilisearch server and writes will behave synchronously.\n\n## Features\n\n- **Synchronous index writes** — document additions, updates, deletions, and setting changes\n  complete before the Lambda returns\n- **Pre-built multi-arch binaries** — `x86_64` and `aarch64` with SHA-256 checksums\n- **Terraform IaC example** — production-ready AWS Lambda + EFS + API Gateway setup\n- **Configurable timeouts** — respects Lambda's own timeout with 1 second of headroom\n- **Minimal overhead** — Rust binary adds ~3 MB and negligible latency to read operations\n- **CORS preflight handling** — OPTIONS requests return `200` without hitting Meilisearch\n\n## Configuration\n\nAll settings are via environment variables:\n\n| Variable                       | Default      | Description                                               |\n| ------------------------------ | ------------ | --------------------------------------------------------- |\n| `MEILI_MASTER_KEY`             | _(required)_ | Meilisearch master key for authentication                 |\n| `AWS_LAMBDA_TIMEOUT_SECONDS`   | `300`        | Lambda timeout; the wrapper stops polling 1 s before this |\n| `MEILISEARCH_POLL_INTERVAL_MS` | `100`        | How often to poll a task's status during a write          |\n| `MAX_REQUEST_BODY_SIZE_MB`     | `100`        | Maximum request body size accepted by the proxy           |\n| `RUST_LOG`                     | `info`       | Log level (`debug`, `info`, `warn`, `error`)              |\n| `AWS_LWA_PORT`                 | `8080`       | Must match the proxy's listen port (do not change)        |\n\nMeilisearch's own environment variables (`MEILI_DB_PATH`, `MEILI_DUMP_DIR`, etc.) are passed\nthrough to the child process. Point these at your EFS mount path.\n\n## Infrastructure\n\nThe combination of **AWS Lambda + Amazon EFS** is central to this project. Lambda provides the\nserverless compute, while EFS provides the persistent, shared file system that Meilisearch needs\nfor its database, dumps, and snapshots — surviving cold starts and scaling across concurrent\ninvocations.\n\nThe [`docs/terraform_example/`](docs/terraform_example/README.md) folder contains a complete,\ndocumented Terraform project that provisions everything you need:\n\n- **ECR** — container registry with lifecycle policy and bootstrap image\n- **Lambda** — arm64 container function (512 MB) with EFS mount and all environment variables\n- **EFS** — encrypted file system with access point and mount targets in every AZ\n- **API Gateway** — REST API with proxy integration and CORS handling\n- **IAM** — least-privilege roles for Lambda ↔ EFS ↔ ECR\n- **Monitoring** — CloudWatch log metric filters, alarms, and SNS email alerts\n\nSee the [Terraform README](docs/terraform_example/README.md) for a step-by-step getting started\nguide.\n\n## FAQ: Meilisearch on AWS Lambda\n\n### Can I run Meilisearch on AWS Lambda?\n\nYes. This project runs Meilisearch inside a Lambda container image, exposes it through Lambda Web\nAdapter, and stores Meilisearch data on Amazon EFS so indexes survive cold starts.\n\n### Do I need Amazon EFS for Meilisearch on Lambda?\n\nYes, for persistent indexes. Lambda's local filesystem is ephemeral, so Meilisearch database, dump,\nand snapshot paths should point to an EFS mount.\n\n### Does Lambda Web Adapter alone solve Meilisearch writes?\n\nNo. Lambda Web Adapter forwards HTTP requests, but Meilisearch writes are asynchronous. This wrapper\nkeeps the Lambda invocation open and polls Meilisearch task status until the write reaches a terminal\nstate.\n\n### Is serverless Meilisearch production-ready?\n\nThis is best treated as a proof of concept or low-to-moderate traffic deployment pattern. It is a good\nfit for side projects, internal tools, staging environments, and cost-sensitive workloads where\noccasional cold starts and EFS latency are acceptable.\n\n## When should I use this?\n\n**Good fit:**\n\n- Low-to-moderate traffic search workloads\n- Side projects, internal tools, staging environments\n- Cost-sensitive deployments where Lambda's free tier matters\n- Prototyping with real full-text search before committing to infrastructure\n\n**Not ideal for:**\n\n- Use cases requiring sub-second cold starts\n- Workloads where EFS latency on the initial index load is unacceptable (very large indexes)\n\nThis is a **proof of concept**. It works well for the use cases above.\n[Contributions and feedback are welcome!](CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falchemaxinc%2Fmeilisearch-lambda-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falchemaxinc%2Fmeilisearch-lambda-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falchemaxinc%2Fmeilisearch-lambda-wrapper/lists"}