ElasticPress hangs on indexing and/or fails with error “Error: cURL error 28: Operation timed out after [???] milliseconds”

This error occurs when ElasticPress takes too long to send a request to ElasticPress.io, or the processing of that request by ElasticPress.io takes longer than the timeout on the originating server.

The most common reasons for this error are syncing too many posts per bulk index request, and trying to sync too many Documents per index request. In particular, since Documents tend to be larger than basic posts, indexing them often requires a lower Content Items per Index Cycle setting than the default value of 350.

The Content Items per Index Cycle is the number of posts or any other WordPress object (such as Custom Post Type entries) that is indexed by ElasticPress.io and available for search or query. The default setting of 350 per cycle indexes 350 content objects per HTTP request. This is very efficient for rapidly indexing large numbers of relatively small content objects (like Posts) but can be an issue with larger content objects or slower network connections.

If you encounter this error, here are some steps to take to resolve it:

  1. If the timeout is rather short (under 30,000 milliseconds) try increasing the PHP timeout on the server (if possible).
  2. If the timeout is >= 30,000 milliseconds, or you are not able to alter your PHP timeout, reduce the Content Items per Index Cycle from 350 to a very low number, such as 1 or 5, and repeat the indexing process. If successful, you can increase this number further, but be aware that additional items per cycle will increase the corresponding execution time and could cause future indexing operations to fail. The Content Items per Index Cycle setting is available in the ElasticPress -> Settings menu of the site’s WordPress Dashboard.
  3. If you have very large Documents or prefer to test with WP-CLI, indexing through WP-CLI with the –nobulk option will cause ElasticPress to index a single record per request to ElasticPress.io. The full command to perform an index in this case would be: wp elasticpress sync --nobulk with the –setup flag as an optional addition if you also want to delete and recreate the index during the sync operation. Adding the –setup flag will delete any data in the index, so only use this in the case where you are seeing unexpected behavior and it is acceptable to disable ElasticPress search while the index rebuilds. You can also set the content items to index per cycle with WP-CLI, using the –per-page option:  wp elasticpress sync --per-page=5. Using the –per-page flag overrides the value set in the Settings screen.