# ----------------------------------------------------------------------- # Rate limiting for /search and the AI vector-search endpoints # # Laravel already throttles these routes at the application layer # (see App\Providers\AppServiceProvider::configureSearchRateLimiter / # configureVectorSearchRateLimiter), but that still costs one PHP-FPM # worker per request just to run the rate limiter and reject the # request. This nginx-level limiter rejects floods with a 503 before # they ever reach FPM, which is what actually protects worker capacity # during a scripted flood or bot storm. # # Setup: # 1. Add the `limit_req_zone` and `limit_req_status` lines to the # `http {}` block (nginx.conf or conf.d/00-rate-limit-zones.conf) — # zones MUST be declared at http level, not inside server {}. # 2. Include the `location` blocks below inside the relevant # `server {}` block, ABOVE the general `location ~ \.php$` / # PHP-FPM passthrough. # ----------------------------------------------------------------------- # --- Add to the http {} block --------------------------------------------- # limit_req_zone $binary_remote_addr zone=search_zone:10m rate=20r/m; # limit_req_zone $binary_remote_addr zone=ai_search_zone:10m rate=10r/m; # limit_req_status 429; # limit_req_log_level warn; # --------------------------------------------------------------------------- # Human search traffic: /search page + /api/search/* (Meilisearch-backed, # cheap once app-level caching is warm — burst allowance covers pagination # clicks / autocomplete without tripping on normal use). location ~ ^/(search|api/search) { limit_req zone=search_zone burst=15 nodelay; try_files $uri $uri/ /index.php?$query_string; } # AI similarity / image-search endpoints: each request can trigger an # outbound HTTP call to the vision vector gateway (see # App\Services\Vision\VectorGatewayClient), so keep the burst tight — # a flood here is the "consuming FPM workers" scenario from the slow log. location ~ ^/api/(art/[0-9]+/similar-ai|search/image) { limit_req zone=ai_search_zone burst=5 nodelay; try_files $uri $uri/ /index.php?$query_string; }