{"_id":"5a8fae0368264c001f20cc11","category":{"_id":"5a8fae0368264c001f20cc03","version":"5a8fae0268264c001f20cc00","project":"5633ebff7e9e880d00af1a53","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-12-23T20:11:49.377Z","from_sync":false,"order":5,"slug":"best-practices","title":"Elasticsearch Tips & Tricks"},"project":"5633ebff7e9e880d00af1a53","parentDoc":null,"user":"5633ec9b35355017003ca3f2","version":{"_id":"5a8fae0268264c001f20cc00","project":"5633ebff7e9e880d00af1a53","__v":2,"createdAt":"2018-02-23T06:00:34.961Z","releaseDate":"2018-02-23T06:00:34.961Z","categories":["5a8fae0268264c001f20cc01","5a8fae0268264c001f20cc02","5a8fae0368264c001f20cc03","5a8fae0368264c001f20cc04","5a8fae0368264c001f20cc05","5a8fae0368264c001f20cc06","5a8fae0368264c001f20cc07","5a8fae0368264c001f20cc08","5a8fae0368264c001f20cc09","5abaa7eb72d6dc0028a07bf3"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"2.0.0","version":"2.0"},"__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-12-23T20:12:01.655Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"Bonsai implements connection management as a [metered plan resource](doc:metering-on-bonsai#concurrent-connections). Our connection management proxy is designed to help model and encourage best practices for using Elasticsearch efficiently at different cluster sizes. \n\nThis document outlines several additional strategies that users can take to maximize the performance and throughput for their cluster.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Implement HTTP Keep-alive\"\n}\n[/block]\nNormally when an application makes a request to the cluster, it needs to perform a lot of steps. Very generally, it looks like this:\n\n* Set up the connection locally\n* Reach the target server\n* Establish a secure communication protocol via SSL/TLS (this step is actually a dozen smaller steps, see [The SSL/TLS Handshake](https://www.ssl.com/article/ssl-tls-handshake-overview/) for an infographic)\n* Send the authentication credentials and the request\n* Wait for a response\n* Receive the response\n* Tear down the connection\n* Return the response to the application\n\nAs you can see, there is quite a bit of overhead to accomplish a simple search request. There is an optimization to be made here, called [HTTP keep-alive](https://en.wikipedia.org/wiki/HTTP_persistent_connection). Essentially, the application opens a persistent connection to the cluster and may send and receive multiple search requests over it without the need to perform redundant tasks like negotiating a cryptographic protocol.\n\nPersistent connections are \"free\" on Bonsai; the [concurrency allowances](doc:metering-on-bonsai#concurrent-connections) only apply to active, in-flight connections. Otherwise idle HTTP keep-alive connections are **not** tracked toward this limit. Users should maintain a reasonably sized pool of keep-alive connections to reduce the setup cost of each connection and reduce the average latency.\n\nThis strategy saves a significant amount of overhead and reduces overall request latencies substantially. Some benchmarks of applications in production have seen a 20-25% improvement in throughput (requests per second) by implementing HTTP keep-alive. \n\nIn the ideal implementation, the application would have access to a local pool of persistent connections, from which it would draw to perform search requests. The local pool would also queue requests when all persistent connections are in use. This implementation would allow the developer to fine-tune the local pool size to minimize latency without exceeding the concurrency allowance for the cluster's plan.\n\nConsult the documentation for your Elasticsearch client for more details on implementing this feature.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Utilize a Durable Message Queue\"\n}\n[/block]\nFor best performance and reliability, updates to data should be pushed into a durable message queue for asynchronous grouping and processing in batches. Some examples of message queues are: Apache Kafka, AWS Kinesis, IronMQ, Disque, Redis, Rescue, and RabbitMQ.\n\nThese services are resistant to network partitions and random node outages. There may be times, particularly on [multi tenant class](doc:architecture-classes#multi-tenant-class) clusters, where a node is randomly restarted. Consider a case where an application pushes updates directly in to Elasticsearch. Such an interruption, even for a few seconds, could lead to error logs and emails about [HTTP 503](error-codes#http-503-service-unavailable) responses.\n\nBut with a message queue acting as an intermediary, temporary connection issues are resolved automatically, and the application does not need to bubble up errors to the user or administrators. A message queue can also avoid the overhead of single-document updates by passing updates in batches. This strategy is one way to avoid an [HTTP 429](doc:error-codes#http-429-too-many-requests) response.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Prefer Bulk Updates Over Single-Document Updates\"\n}\n[/block]\nIt's worth noting that Bonsai distinguishes Bulk API updates from other writes. This is because the Bulk API is the more efficient means of data ingress into Elasticsearch, and is the preferred means of data ingest to the cluster. Single-document updates are helpful for maintaining synchronization over time, but should be avoided as a means for mass ingest.\n\nBatch sizes should be determined experimentally based on your document size. A good heuristic is to aim for a batch size that takes approximately 1 second to complete. If requests are slower than one second, reduce the batch size. If requests are consistently faster than one-second, add more documents to the batch size. Repeat until bulk updates average about 1 second.","excerpt":"","slug":"connection-management","type":"basic","title":"Improving Throughput and Performance"}

Improving Throughput and Performance


Bonsai implements connection management as a [metered plan resource](doc:metering-on-bonsai#concurrent-connections). Our connection management proxy is designed to help model and encourage best practices for using Elasticsearch efficiently at different cluster sizes. This document outlines several additional strategies that users can take to maximize the performance and throughput for their cluster. [block:api-header] { "type": "basic", "title": "Implement HTTP Keep-alive" } [/block] Normally when an application makes a request to the cluster, it needs to perform a lot of steps. Very generally, it looks like this: * Set up the connection locally * Reach the target server * Establish a secure communication protocol via SSL/TLS (this step is actually a dozen smaller steps, see [The SSL/TLS Handshake](https://www.ssl.com/article/ssl-tls-handshake-overview/) for an infographic) * Send the authentication credentials and the request * Wait for a response * Receive the response * Tear down the connection * Return the response to the application As you can see, there is quite a bit of overhead to accomplish a simple search request. There is an optimization to be made here, called [HTTP keep-alive](https://en.wikipedia.org/wiki/HTTP_persistent_connection). Essentially, the application opens a persistent connection to the cluster and may send and receive multiple search requests over it without the need to perform redundant tasks like negotiating a cryptographic protocol. Persistent connections are "free" on Bonsai; the [concurrency allowances](doc:metering-on-bonsai#concurrent-connections) only apply to active, in-flight connections. Otherwise idle HTTP keep-alive connections are **not** tracked toward this limit. Users should maintain a reasonably sized pool of keep-alive connections to reduce the setup cost of each connection and reduce the average latency. This strategy saves a significant amount of overhead and reduces overall request latencies substantially. Some benchmarks of applications in production have seen a 20-25% improvement in throughput (requests per second) by implementing HTTP keep-alive. In the ideal implementation, the application would have access to a local pool of persistent connections, from which it would draw to perform search requests. The local pool would also queue requests when all persistent connections are in use. This implementation would allow the developer to fine-tune the local pool size to minimize latency without exceeding the concurrency allowance for the cluster's plan. Consult the documentation for your Elasticsearch client for more details on implementing this feature. [block:api-header] { "type": "basic", "title": "Utilize a Durable Message Queue" } [/block] For best performance and reliability, updates to data should be pushed into a durable message queue for asynchronous grouping and processing in batches. Some examples of message queues are: Apache Kafka, AWS Kinesis, IronMQ, Disque, Redis, Rescue, and RabbitMQ. These services are resistant to network partitions and random node outages. There may be times, particularly on [multi tenant class](doc:architecture-classes#multi-tenant-class) clusters, where a node is randomly restarted. Consider a case where an application pushes updates directly in to Elasticsearch. Such an interruption, even for a few seconds, could lead to error logs and emails about [HTTP 503](error-codes#http-503-service-unavailable) responses. But with a message queue acting as an intermediary, temporary connection issues are resolved automatically, and the application does not need to bubble up errors to the user or administrators. A message queue can also avoid the overhead of single-document updates by passing updates in batches. This strategy is one way to avoid an [HTTP 429](doc:error-codes#http-429-too-many-requests) response. [block:api-header] { "type": "basic", "title": "Prefer Bulk Updates Over Single-Document Updates" } [/block] It's worth noting that Bonsai distinguishes Bulk API updates from other writes. This is because the Bulk API is the more efficient means of data ingress into Elasticsearch, and is the preferred means of data ingest to the cluster. Single-document updates are helpful for maintaining synchronization over time, but should be avoided as a means for mass ingest. Batch sizes should be determined experimentally based on your document size. A good heuristic is to aim for a batch size that takes approximately 1 second to complete. If requests are slower than one second, reduce the batch size. If requests are consistently faster than one-second, add more documents to the batch size. Repeat until bulk updates average about 1 second.