
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Implementing full-text search in Laravel with Meilisearch and Scout solves the performance bottlenecks inherent in traditional database LIKE queries while delivering typo-tolerant, instant results. As your application data grows beyond a few thousand records, MySQL or PostgreSQL full-text indexes often fail to provide sub-second latency or relevance tuning without significant operational overhead. This guide walks you through a production-grade integration that balances developer experience with the rigorous performance demands of modern web applications.
meilisearch/meilisearch-php and laravel/scout packages, configure your credentials in .env, make your Eloquent models searchable, and run php artisan scout:import to sync existing data. Meilisearch handles indexing and querying via Scout's driver, providing instant, typo-tolerant results without managing complex Elasticsearch clusters.How do you configure full-text search in Laravel with Meilisearch and Scout?
Setting up full-text search in Laravel with Meilisearch and Scout requires coordinating three distinct layers: the Laravel application, the Scout abstraction package, and the Meilisearch engine itself. A common mistake I see in audits is treating this as a simple composer install; in production, you must consider how these components communicate securely and efficiently. Before diving into code, ensure your infrastructure supports this architecture. If you are deploying to a VPS, refer to our guide on deploying Laravel on Ubuntu with Nginx to ensure your server has adequate resources for both PHP-FPM and the Meilisearch binary.
Installation and environment configuration
Begin by installing the required Composer dependencies. In 2026, Meilisearch v1.12+ and Scout v10.x are the stable production targets:
composer require laravel/scout meilisearch/meilisearch-php http-interop/http-factory-guzzle Publish the Scout configuration file to customize driver behavior:
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider" In your .env file, set the driver and connection details. Never commit master keys to version control; use read-only API keys for application-level searching:
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=your-master-key-or-search-key Making models searchable
Add the Searchable trait to any Eloquent model you want indexed. For a Product model, define which attributes should be included in the index via the toSearchableArray method. This is where you control data shape and reduce index size:
use Laravel\Scout\Searchable;
class Product extends Model
{
use Searchable;
public function toSearchableArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => strip_tags($this->description),
'sku' => $this->sku,
'category' => $this->category?->name,
'price' => $this->price,
'created_at' => $this->created_at->timestamp,
];
}
} How does Meilisearch compare to Elasticsearch for Laravel projects?
Choosing between Meilisearch and Elasticsearch is a frequent architectural decision when implementing full-text search in Laravel with Meilisearch and Scout. While Elasticsearch remains the industry standard for massive-scale analytics and complex aggregations, Meilisearch has carved out a definitive niche for application-level search where developer velocity and predictable relevance matter more than raw cluster scale.
| Criteria | Meilisearch | Elasticsearch |
|---|---|---|
| Setup Complexity | Single binary, zero-config defaults | Multi-node cluster, JVM tuning required |
| Relevance Tuning | Built-in typo tolerance, synonyms | Manual scoring scripts, analyzers |
| Resource Usage | ~200MB RAM baseline | 2GB+ RAM minimum per node |
| Laravel Integration | Native Scout driver, first-party | Community drivers, config drift |
| Analytics & Aggregations | Limited facet support | Full aggregation pipeline |
| Best For | E-commerce, docs, SaaS search | Log analysis, observability, big data |
In my experience helping Nepali startups and global teams alike, Meilisearch wins for 90% of Laravel applications. The operational savings are substantial: no JVM heap management, no shard rebalancing headaches, and updates that don't require rolling restarts. Reserve Elasticsearch for cases where you need to aggregate millions of log entries or perform geospatial analytics at scale.
How do you optimize indexing performance for large datasets?
Indexing strategy separates toy implementations from production systems. When building full-text search in Laravel with Meilisearch and Scout, naive bulk imports can overwhelm your database and delay search availability. Understanding the synchronization pipeline helps you avoid these pitfalls.
Chunked imports and queue configuration
Always enable queue-based syncing in config/scout.php. Synchronous indexing blocks user requests and creates cascading failures under load:
'queue' => [
'connection' => 'redis',
'queue' => 'scout-indexing',
], For initial imports of existing data, use chunked processing to manage memory and respect Meilisearch's payload limits. The default chunk size of 500 works well for most schemas, but adjust based on your document size:
php artisan scout:import "App\Models\Product" --chunk=500 If you're containerizing this workflow, our Docker for Laravel guide covers running Meilisearch alongside your app in development. In production, I recommend dedicated Meilisearch Cloud instances or self-hosted deployments with persistent volumes—never ephemeral containers for search indexes.
Customizing searchable data and filters
Reduce index size and improve query speed by excluding unnecessary fields. Use conditional logic in toSearchableArray to skip soft-deleted or unpublished records:
public function shouldBeSearchable()
{
return $this->is_published && !$this->trashed();
}
public function toSearchableArray()
{
$data = $this->toArray();
// Remove heavy relationships not needed for search
unset($data['full_description'], $data['metadata']);
// Add computed fields for filtering
$data['in_stock'] = $this->inventory_count > 0;
$data['price_range'] = match(true) {
$this->price < 1000 => 'budget',
$this->price < 5000 => 'mid',
default => 'premium',
};
return $data;
} How do you implement advanced filtering and faceted search?
Basic text matching is table stakes. Real-world full-text search in Laravel with Meilisearch and Scout requires combining relevance with structured filters. Meilisearch distinguishes between filterable attributes (exact match, range) and sortable attributes, requiring explicit configuration.
Configuring filterable and sortable attributes
Create a dedicated Artisan command or migration to set index settings. Relying on auto-detection leads to inconsistent behavior across environments:
use Meilisearch\Client;
$client = new Client(config('scout.meilisearch.host'), config('scout.meilisearch.key'));
$index = $client->index('products');
$index->updateFilterableAttributes([
'category',
'in_stock',
'price_range',
'created_at',
]);
$index->updateSortableAttributes([
'price',
'created_at',
]); Executing filtered searches in controllers
Scout's builder exposes Meilisearch's filter syntax directly. Combine text queries with structured constraints for precise results:
$results = Product::search($request->input('q'))
->where('in_stock', true)
->where('category', 'electronics')
->orderBy('price', 'asc')
->paginate(20);
// Advanced filter syntax for ranges/OR conditions
$results = Product::search($request->input('q'))
->raw() // Access underlying Meilisearch client
->search([
'filter' => 'price >= 1000 AND price <= 5000 AND (category = "electronics" OR category = "gadgets")',
'facets' => ['category', 'price_range'],
]); This hybrid approach gives you the simplicity of Scout's Eloquent integration with the power of Meilisearch's native filtering when needed. For teams managing multiple services, integrating this with a robust CI/CD pipeline ensures index settings stay synchronized across staging and production. See our GitLab CI for Laravel tutorial for automation patterns.
What are the best practices for monitoring and maintaining search indexes?
Search infrastructure fails silently. Without observability, you won't know your index is stale or your queries are degrading until users complain. Treat full-text search in Laravel with Meilisearch and Scout as a first-class production service requiring the same rigor as your primary database.
- Monitor index lag: Track the time between model updates and index reflection. Scout provides events like
ModelsImported; log these to your observability stack. If you use Prometheus, our monitoring setup guide covers custom metric exporters. - Set up health checks: Meilisearch exposes
/healthand/statsendpoints. Integrate these into your load balancer health checks and alerting. A 5xx on search should page on-call just like a database failure. - Version your index settings: Store filterable/sortable attribute configurations in version-controlled migrations or deployment scripts. Drift between environments causes subtle bugs that surface only in production.
- Plan for reindexing: Schema changes require full reimports. Schedule these during low-traffic windows and use Meilisearch's swap feature to avoid downtime: create a new index, import data, then atomically swap aliases.
- Audit search queries: Enable Meilisearch's analytics or forward query logs to understand what users actually search for. Missing synonyms and typos reveal gaps in your relevance configuration.
Security matters equally. Restrict Meilisearch access via network policies; never expose port 7700 publicly. Use scoped API keys with tenant tokens for multi-tenant applications, ensuring users can only search their own data. This aligns with SOC 2 and ISO 27001 controls around data isolation and least privilege.
Next steps for production-ready Laravel search
Implementing full-text search in Laravel with Meilisearch and Scout delivers immediate UX improvements, but long-term success depends on treating search as an engineered system, not an afterthought. Start with the basics outlined here, measure real query performance, and iterate on relevance based on actual user behavior rather than assumptions. If your team needs help architecting scalable search infrastructure, passing compliance audits, or optimizing cloud costs around search workloads, reach out to discuss your specific requirements.