Search Engine Unavailable Overview
Symptoms
Indicators:
├── Elasticsearch cluster red/yellow
├── Search queries failing
├── Autocomplete not working
├── Faceted search broken
├── Indexing failures
└── Application errors
Impact:
├── Product search broken
├── Category pages empty
├── Poor user experience
├── Lost sales
└── SEO impact
Detection
# Check cluster health
curl -XGET 'localhost:9200/_cluster/health?pretty'
# Check node status
curl -XGET 'localhost:9200/_cat/nodes?v'
# Check index status
curl -XGET 'localhost:9200/_cat/indices?v'
# Check pending tasks
curl -XGET 'localhost:9200/_cluster/pending_tasks?pretty'
Common Causes
1. Cluster health red (unassigned shards)
2. Disk space full
3. JVM heap overflow
4. Network partition
5. Node failure
6. Index corruption
7. Too many shards
8. Slow queries
Failover Strategies
Fallback to Database
// Search with fallback
class SearchService
{
public function search($query)
{
try {
// Try Elasticsearch first
return $this->elasticsearch->search($query);
} catch (\Exception $e) {
$this->logger->warning('Elasticsearch failed', [
'error' => $e->getMessage()
]);
// Fallback to database
return $this->databaseFallback($query);
}
}
private function databaseFallback($query)
{
// Use MySQL full-text search
$results = $this->db->fetchAll(
"SELECT * FROM catalog_product_entity
WHERE MATCH(name, description) AGAINST(? IN BOOLEAN MODE)
LIMIT 20",
[$query]
);
return [
'hits' => $results,
'total' => count($results),
'fallback' => true
];
}
}
Cached Search Results
// Use cached results during outage
public function searchWithCache($query)
{
$cacheKey = 'search_' . md5($query);
try {
$results = $this->elasticsearch->search($query);
// Cache successful results
$this->cache->save(serialize($results), $cacheKey, [], 3600);
return $results;
} catch (\Exception $e) {
// Try cache
$cached = $this->cache->load($cacheKey);
if ($cached) {
$results = unserialize($cached);
$results['cached'] = true;
return $results;
}
// Fallback to database
return $this->databaseFallback($query);
}
}
Circuit Breaker
// Circuit breaker for search
class SearchCircuitBreaker
{
private $failureCount = 0;
private $lastFailureTime = 0;
private $state = 'closed'; // closed, open, half-open
public function call($callback)
{
if ($this->state === 'open') {
if (time() - $this->lastFailureTime > 60) {
$this->state = 'half-open';
} else {
throw new \Exception('Circuit breaker open');
}
}
try {
$result = $callback();
$this->reset();
return $result;
} catch (\Exception $e) {
$this->failureCount++;
$this->lastFailureTime = time();
if ($this->failureCount >= 5) {
$this->state = 'open';
}
throw $e;
}
}
private function reset()
{
$this->failureCount = 0;
$this->state = 'closed';
}
}
Degraded Mode Operation
Graceful Degradation
// Degraded search mode
public function searchDegraded($query)
{
// Disable advanced features
$features = [
'autocomplete' => false,
'facets' => false,
'personalization' => false,
'spell_check' => false
];
// Use basic search only
$results = $this->basicSearch($query);
// Show degraded notice
$results['notice'] = 'Search is operating in reduced mode';
return $results;
}
// Basic search using database
private function basicSearch($query)
{
return $this->db->fetchAll(
"SELECT entity_id, sku, name, price
FROM catalog_product_entity
JOIN catalog_product_entity_varchar ON ...
WHERE name LIKE ?
LIMIT 20",
['%' . $query . '%']
);
}
Feature Flags
// Control features during outage
public function getFeatures()
{
$searchAvailable = $this->checkSearchHealth();
return [
'search' => $searchAvailable,
'autocomplete' => $searchAvailable,
'facets' => $searchAvailable,
'recommendations' => $searchAvailable,
'basic_search' => true // Always available
];
}
// Use in frontend
if ($features['autocomplete']) {
// Show autocomplete
} else {
// Hide autocomplete
// Show basic search input only
}
Resolution Steps
Cluster Recovery
# Check unassigned shards
curl -XGET 'localhost:9200/_cat/shards?v&h=index,shard,prirep,state,unassigned.reason'
# Reroute unassigned shards
curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
"commands": [{
"allocate_stale_primary": {
"index": "catalog_product",
"shard": 0,
"node": "node1",
"accept_data_loss": true
}
}]
}'
# Increase disk watermarks
curl -XPUT 'localhost:9200/_cluster/settings' -d '{
"transient": {
"cluster.routing.allocation.disk.watermark.low": "90%",
"cluster.routing.allocation.disk.watermark.high": "95%"
}
}'
# Restart failed nodes
sudo systemctl start elasticsearch
Index Recovery
# Rebuild corrupted index
curl -XDELETE 'localhost:9200/catalog_product'
# Then reindex from database
bin/magento indexer:reindex catalogsearch_fulltext
# Optimize index
curl -XPOST 'localhost:9200/catalog_product/_optimize'
# Check index health
curl -XGET 'localhost:9200/_cat/indices?v'
Verification
// Test search after recovery
public function testSearch()
{
$queries = ['wireless', 'headphones', 'blue', 'sale'];
foreach ($queries as $query) {
$results = $this->searchService->search($query);
if (empty($results['hits'])) {
throw new \Exception('Search failed for: ' . $query);
}
}
// Check cluster health
$health = $this->elasticsearch->cluster()->health();
if ($health['status'] !== 'green') {
throw new \Exception('Cluster not healthy: ' . $health['status']);
}
}
Practice Problems
Elasticsearch cluster goes red with unassigned shards during peak traffic.
Solution
// Response:
// 1. Check: _cluster/health, _cat/shards
// 2. Fallback: Database search + cached results
// 3. Degraded: Basic search only
// 4. Recovery: Fix unassigned shards
// 5. Verify: Test search functionality
// 6. Prevent: Monitor disk, JVM heap Quiz
1. What should you do when Elasticsearch is unavailable?
2. What is degraded mode?
3. What is a circuit breaker?
4. How to recover a corrupted index?
Flashcards
Question
Search unavailable fallback?
Click to reveal answer
Answer
Fall back to database full-text search
Question
Degraded mode?
Click to reveal answer
Answer
Advanced features disabled, basic search works
Question
Circuit breaker purpose?
Click to reveal answer
Answer
Stop calling failing services to prevent cascade
Question
Corrupted index fix?
Click to reveal answer
Answer
Delete and rebuild from database
Question
Search health check?
Click to reveal answer
Answer
_cluster/health, _cat/indices, _cat/shards
Revision Notes
Key Takeaways
- 1. Fallback: Database search when Elasticsearch fails
- 2. Degraded mode: Basic search only, no facets/autocomplete
- 3. Circuit breaker: Stop calling failing services
- 4. Recovery: Delete and rebuild corrupted index
- 5. Health: _cluster/health, _cat/indices
Interview Tips
- • Explain failover strategies
- • Discuss degraded mode implementation
- • Know circuit breaker pattern
- • Understand index recovery process
Cheat Sheet
Search Unavailable
- Fallback: Database full-text search
- Degraded: Basic search, no facets
- Circuit breaker: Stop failing calls
- Recovery: Delete + rebuild index
- Health: _cluster/health, _cat/indices