diff --git a/ChangeLog.d/bugfix/ZBX-24549 b/ChangeLog.d/bugfix/ZBX-24549
new file mode 100644
index 00000000000..b4008287d79
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-24549
@@ -0,0 +1 @@
+........S. [ZBX-24549] added lower bounds and limiting by global history storage period in query filter for Elasticsearch; added slow query log for elastic; fixed queries not working with Elastic search 8.16.1 (vso)
diff --git a/include/zbx_dbversion_constants.h b/include/zbx_dbversion_constants.h
index cd9aeb1e819..7cea995f5d9 100644
--- a/include/zbx_dbversion_constants.h
+++ b/include/zbx_dbversion_constants.h
@@ -51,8 +51,8 @@
 
 #define ZBX_ELASTIC_MIN_VERSION					70000
 #define ZBX_ELASTIC_MIN_VERSION_STR				"7.x"
-#define ZBX_ELASTIC_MAX_VERSION					79999
-#define ZBX_ELASTIC_MAX_VERSION_STR				ZBX_ELASTIC_MIN_VERSION_STR
+#define ZBX_ELASTIC_MAX_VERSION					89999
+#define ZBX_ELASTIC_MAX_VERSION_STR				"8.x"
 
 #define ZBX_TIMESCALE_MIN_VERSION				20001
 #define ZBX_TIMESCALE_MIN_VERSION_STR				"2.0.1"
diff --git a/include/zbxhistory.h b/include/zbxhistory.h
index d17197e7a30..9c4b7c7547e 100644
--- a/include/zbxhistory.h
+++ b/include/zbxhistory.h
@@ -48,7 +48,7 @@ void	zbx_history_value2variant(const zbx_history_value_t *value, unsigned char v
 #define zbx_history_record_vector_create(vector)	zbx_vector_history_record_create(vector)
 
 int	zbx_history_init(const char *config_history_storage_url, const char *config_history_storage_opts,
-		char **error);
+		int config_log_slow_queries, char **error);
 void	zbx_history_destroy(void);
 
 typedef struct
diff --git a/src/libs/zbxhistory/history.c b/src/libs/zbxhistory/history.c
index 15a4cd70d07..9896f797bc2 100644
--- a/src/libs/zbxhistory/history.c
+++ b/src/libs/zbxhistory/history.c
@@ -40,7 +40,7 @@ zbx_history_iface_t	history_ifaces[ITEM_VALUE_TYPE_BIN + 1];
  *                                                                                  *
  ************************************************************************************/
 int	zbx_history_init(const char *config_history_storage_url, const char *config_history_storage_opts,
-		char **error)
+		int config_log_slow_queries, char **error)
 {
 	/* TODO: support per value type specific configuration */
 
@@ -62,8 +62,11 @@ int	zbx_history_init(const char *config_history_storage_url, const char *config_
 				return FAIL;
 			}
 
-			if (FAIL == zbx_history_elastic_init(&history_ifaces[i], i, config_history_storage_url, error))
+			if (FAIL == zbx_history_elastic_init(&history_ifaces[i], i, config_history_storage_url,
+					config_log_slow_queries, error))
+			{
 				return FAIL;
+			}
 		}
 	}
 
diff --git a/src/libs/zbxhistory/history.h b/src/libs/zbxhistory/history.h
index 0b6911467a7..fe6bc20ee22 100644
--- a/src/libs/zbxhistory/history.h
+++ b/src/libs/zbxhistory/history.h
@@ -36,6 +36,7 @@ struct zbx_history_iface
 {
 	unsigned char			value_type;
 	unsigned char			requires_trends;
+	unsigned char			requires_refresh;
 	union
 	{
 		void				*elastic_data;
@@ -45,6 +46,7 @@ struct zbx_history_iface
 	zbx_history_add_values_func_t	add_values;
 	zbx_history_get_values_func_t	get_values;
 	zbx_history_flush_func_t	flush;
+	int				config_log_slow_queries;
 };
 
 /* SQL hist */
@@ -52,7 +54,7 @@ void	zbx_history_sql_init(zbx_history_iface_t *hist, unsigned char value_type);
 
 /* elastic hist */
 int	zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type,
-		const char *config_history_storage_url, char **error);
+		const char *config_history_storage_url, int config_log_slow_queries, char **error);
 void	zbx_elastic_version_extract(struct zbx_json *json, int *result, int config_allow_unsupported_db_versions,
 		const char *config_history_storage_url);
 zbx_uint32_t	zbx_elastic_version_get(void);
diff --git a/src/libs/zbxhistory/history_elastic.c b/src/libs/zbxhistory/history_elastic.c
index a4def7387b4..ad4ba3d34aa 100644
--- a/src/libs/zbxhistory/history_elastic.c
+++ b/src/libs/zbxhistory/history_elastic.c
@@ -17,14 +17,18 @@
 
 #include "zbxalgo.h"
 #include "zbxdb.h"
+#include "zbxjson.h"
 #include "zbxstr.h"
 #include "zbxnum.h"
+#include "zbxtime.h"
 #include "zbxvariant.h"
 #include "zbx_dbversion_constants.h"
+#include <time.h>
 
 #ifdef HAVE_LIBCURL
 
 #include "zbxcurl.h"
+#include "zbxcacheconfig.h"
 
 #define		ZBX_HISTORY_STORAGE_DOWN	10000 /* Timeout in milliseconds */
 
@@ -85,6 +89,14 @@ static size_t	curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata
 	return r_size;
 }
 
+static size_t	curl_ignore_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+	ZBX_UNUSED(ptr);
+	ZBX_UNUSED(userdata);
+
+	return size * nmemb;
+}
+
 static zbx_history_value_t	history_str2value(char *str, unsigned char value_type)
 {
 	zbx_history_value_t	value;
@@ -634,19 +646,32 @@ static void	elastic_destroy(zbx_history_iface_t *hist)
  *           all values from the specified interval if count is zero.               *
  *                                                                                  *
  ************************************************************************************/
-static int	elastic_get_values(zbx_history_iface_t *hist, zbx_uint64_t itemid, int start, int count, int end,
-		zbx_vector_history_record_t *values)
+static int	elastic_get_values_for_period(zbx_history_iface_t *hist, zbx_uint64_t itemid, time_t start, int *count,
+		time_t end, zbx_vector_history_record_t *values)
 {
 	zbx_elastic_data_t	*data = hist->data.elastic_data;
 	size_t			url_alloc = 0, url_offset = 0, id_alloc = 0, scroll_alloc = 0, scroll_offset = 0;
-	int			total, empty, ret;
+	int			empty, ret;
 	CURLcode		err;
 	struct zbx_json		query;
 	struct curl_slist	*curl_headers = NULL;
 	char			*scroll_id = NULL, *scroll_query = NULL, errbuf[CURL_ERROR_SIZE], *error = NULL;
 	CURLoption		opt;
+	double			sec = 0;
 
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+	if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
+	{
+		char	start_str[32], end_str[32];
+
+		strftime(start_str, sizeof(start_str), "%Y-%m-%d %H:%M:%S", localtime(&start));
+		strftime(end_str, sizeof(end_str), "%Y-%m-%d %H:%M:%S", localtime(&end));
+
+		zabbix_log(LOG_LEVEL_DEBUG, "In %s() window:(%s, %s] age: %s count:%d", __func__, start_str, end_str,
+				zbx_age2str(end - start), *count);
+	}
+
+	if (0 != hist->config_log_slow_queries)
+		sec = zbx_time();
 
 	ret = FAIL;
 
@@ -657,15 +682,44 @@ static int	elastic_get_values(zbx_history_iface_t *hist, zbx_uint64_t itemid, in
 		return FAIL;
 	}
 
+	if (1 == hist->requires_refresh)
+	{
+		hist->requires_refresh = 0;
+		url_offset = 0;
+
+		zbx_snprintf_alloc(&data->post_url, &url_alloc, &url_offset, "%s/%s*/_refresh",
+				data->base_url, value_type_str[hist->value_type]);
+
+		if (CURLE_OK != (err = curl_easy_setopt(data->handle, opt = CURLOPT_URL, data->post_url)) ||
+				CURLE_OK != (err = curl_easy_setopt(data->handle, opt = CURLOPT_POSTFIELDS, "")) ||
+				CURLE_OK != (err = curl_easy_setopt(data->handle, opt = CURLOPT_WRITEFUNCTION,
+					curl_ignore_cb)) ||
+				CURLE_OK != (err = curl_easy_setopt(data->handle, opt = CURLOPT_CUSTOMREQUEST, "POST")))
+		{
+			zabbix_log(LOG_LEVEL_ERR, "cannot set cURL option %d: [%s]", (int)opt,
+					curl_easy_strerror(err));
+			ret = FAIL;
+			goto out;
+		}
+
+		zabbix_log(LOG_LEVEL_DEBUG, "elasticsearch refreshing %s", data->post_url);
+
+		page_r.offset = 0;
+		*errbuf = '\0';
+		if (CURLE_OK != (err = curl_easy_perform(data->handle)))
+			elastic_log_error(data->handle, err, errbuf);
+	}
+
+	url_offset = 0;
 	zbx_snprintf_alloc(&data->post_url, &url_alloc, &url_offset, "%s/%s*/_search?scroll=10s", data->base_url,
 			value_type_str[hist->value_type]);
 
 	/* prepare the json query for elasticsearch, apply ranges if needed */
 	zbx_json_init(&query, ZBX_JSON_ALLOCATE);
 
-	if (0 < count)
+	if (0 < *count)
 	{
-		zbx_json_adduint64(&query, "size", count);
+		zbx_json_adduint64(&query, "size", *count);
 		zbx_json_addarray(&query, "sort");
 		zbx_json_addobject(&query, NULL);
 		zbx_json_addobject(&query, "clock");
@@ -689,6 +743,7 @@ static int	elastic_get_values(zbx_history_iface_t *hist, zbx_uint64_t itemid, in
 	zbx_json_addobject(&query, "range");
 	zbx_json_addobject(&query, "clock");
 
+	zbx_json_addstring(&query, "format", "epoch_second", ZBX_JSON_TYPE_STRING);
 	if (0 < start)
 		zbx_json_adduint64(&query, "gt", start);
 
@@ -745,8 +800,6 @@ static int	elastic_get_values(zbx_history_iface_t *hist, zbx_uint64_t itemid, in
 		goto out;
 	}
 
-	total = (0 == count ? -1 : count);
-
 	/* For processing the records, we need to keep track of the total requested and if the response from the */
 	/* elasticsearch server is empty. For this we use two variables, empty and total. If the result is empty or */
 	/* the total reach zero, we terminate the scrolling query and return what we currently have. */
@@ -788,13 +841,15 @@ static int	elastic_get_values(zbx_history_iface_t *hist, zbx_uint64_t itemid, in
 
 			zbx_vector_history_record_append_ptr(values, &hr);
 
-			if (-1 != total)
-				--total;
-
-			if (0 == total)
+			if (0 != *count)
 			{
-				empty = 1;
-				break;
+				(*count)--;
+
+				if (0 == *count)
+				{
+					empty = 1;
+					break;
+				}
 			}
 		}
 
@@ -856,6 +911,13 @@ out:
 
 	curl_slist_free_all(curl_headers);
 
+	if (0 != hist->config_log_slow_queries)
+	{
+		sec = zbx_time() - sec;
+		if (sec > (double)hist->config_log_slow_queries / 1000.0)
+			zabbix_log(LOG_LEVEL_WARNING, "slow query: " ZBX_FS_DBL " sec, \"%s\"", sec, query.buffer);
+	}
+
 	zbx_json_free(&query);
 
 	zbx_free(scroll_id);
@@ -864,11 +926,71 @@ out:
 
 	zbx_vector_history_record_sort(values, (zbx_compare_func_t)zbx_history_record_compare_desc_func);
 
-	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() values:%d", __func__, values->values_num);
 
 	return ret;
 }
 
+static int	period_iter_next(const int *periods, int num, int *step, time_t *clock_from, time_t clock_to,
+		time_t *clock_to_shift)
+{
+	int	period = periods[*step];
+
+	if (-1 == period)
+		return period;
+
+	if (0 > (*clock_from = clock_to - period))
+	{
+		*clock_from = clock_to;
+
+		*step = num - 1;
+
+		return period;
+	}
+
+	*clock_to_shift = clock_to - period;
+	(*step)++;
+
+	return period;
+}
+
+static int	elastic_read_values_by_count(zbx_history_iface_t *hist, zbx_uint64_t itemid, time_t clock_from,
+		int count, time_t clock_to, zbx_vector_history_record_t *values)
+{
+	const int	periods[] = {SEC_PER_HOUR, 12 * SEC_PER_HOUR, SEC_PER_DAY, SEC_PER_DAY, SEC_PER_WEEK,
+				SEC_PER_MONTH, 0, -1};
+	int		step = 0, ret = FAIL;
+	time_t		clock_to_shift;
+
+	while (-1 != period_iter_next(periods, ARRSIZE(periods), &step, &clock_from, clock_to, &clock_to_shift) &&
+			1 < count)
+	{
+		if (clock_from == clock_to)
+			clock_from = 0;
+
+		zbx_recalc_time_period(&clock_from, ZBX_RECALC_TIME_PERIOD_HISTORY);
+
+		if (clock_from > clock_to)
+			return SUCCEED;
+
+		if (FAIL == (ret = elastic_get_values_for_period(hist, itemid, clock_from, &count, clock_to, values)))
+			break;
+
+		clock_to = clock_to_shift;
+	}
+
+	return ret;
+}
+
+static int	elastic_get_values(zbx_history_iface_t *hist, zbx_uint64_t itemid, int start, int count, int end,
+		zbx_vector_history_record_t *values)
+{
+	if (0 == count || 0 != start)
+		return elastic_get_values_for_period(hist, itemid, start, &count, end, values);
+
+	return elastic_read_values_by_count(hist, itemid, start, count, end, values);
+}
+
 /************************************************************************************
  *                                                                                  *
  * Purpose: sends history data to the storage                                       *
@@ -943,7 +1065,7 @@ static int	elastic_add_values(zbx_history_iface_t *hist, const zbx_vector_dc_his
 
 	if (num > 0)
 	{
-		data->post_url = zbx_dsprintf(NULL, "%s/_bulk?refresh=true", data->base_url);
+		data->post_url = zbx_dsprintf(NULL, "%s/_bulk", data->base_url);
 		elastic_writer_add_iface(hist);
 	}
 
@@ -966,7 +1088,7 @@ static int	elastic_add_values(zbx_history_iface_t *hist, const zbx_vector_dc_his
  ************************************************************************************/
 static int	elastic_flush(zbx_history_iface_t *hist)
 {
-	ZBX_UNUSED(hist);
+	hist->requires_refresh = 1;
 
 	return elastic_writer_flush();
 }
@@ -986,7 +1108,7 @@ static int	elastic_flush(zbx_history_iface_t *hist)
  *                                                                                  *
  ************************************************************************************/
 int	zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type,
-		const char *config_history_storage_url, char **error)
+		const char *config_history_storage_url, int config_log_slow_queries, char **error)
 {
 	zbx_elastic_data_t	*data;
 
@@ -1014,6 +1136,8 @@ int	zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type
 	hist->flush = elastic_flush;
 	hist->get_values = elastic_get_values;
 	hist->requires_trends = 0;
+	hist->requires_refresh = 0;
+	hist->config_log_slow_queries = config_log_slow_queries;
 
 	return SUCCEED;
 }
@@ -1189,12 +1313,13 @@ zbx_uint32_t	zbx_elastic_version_get(void)
 	return ZBX_ELASTIC_SVERSION;
 }
 #else
-int	zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type,
-		const char *config_history_storage_url, char **error)
+iint	zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type,
+		const char *config_history_storage_url, int config_log_slow_queries, char **error)
 {
 	ZBX_UNUSED(hist);
 	ZBX_UNUSED(value_type);
 	ZBX_UNUSED(config_history_storage_url);
+	ZBX_UNUSED(config_log_slow_queries);
 
 	*error = zbx_strdup(*error, "Zabbix must be compiled with cURL library for Elasticsearch history backend");
 
diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c
index ff4941ecf36..cfb45ca18e5 100644
--- a/src/zabbix_server/server.c
+++ b/src/zabbix_server/server.c
@@ -2320,7 +2320,8 @@ int	MAIN_ZABBIX_ENTRY(int flags)
 		exit(EXIT_FAILURE);
 	}
 
-	if (SUCCEED != zbx_history_init(config_history_storage_url, config_history_storage_opts, &error))
+	if (SUCCEED != zbx_history_init(config_history_storage_url, config_history_storage_opts,
+			config_log_slow_queries, &error))
 	{
 		zabbix_log(LOG_LEVEL_CRIT, "cannot initialize history storage: %s", error);
 		zbx_free(error);
diff --git a/tests/libs/zbxhistory/zbx_history_get_values.c b/tests/libs/zbxhistory/zbx_history_get_values.c
index 9940fcdbe28..a69e3835af6 100644
--- a/tests/libs/zbxhistory/zbx_history_get_values.c
+++ b/tests/libs/zbxhistory/zbx_history_get_values.c
@@ -309,7 +309,7 @@ void	zbx_mock_test_entry(void **state)
 
 	zbx_mockdb_init();
 
-	err = zbx_history_init(NULL, NULL, &error);
+	err = zbx_history_init(NULL, NULL, 0, &error);
 	zbx_mock_assert_result_eq("zbx_history_init()", SUCCEED, err);
 
 	if (FAIL == zbx_is_uint64(zbx_mock_get_parameter_string("in.itemid"), &itemid))
diff --git a/tests/mocks/valuecache/valuecache_mock.c b/tests/mocks/valuecache/valuecache_mock.c
index 2a9f73fe4a8..820a01b916e 100644
--- a/tests/mocks/valuecache/valuecache_mock.c
+++ b/tests/mocks/valuecache/valuecache_mock.c
@@ -51,7 +51,7 @@ int	__wrap_zbx_history_get_values(zbx_uint64_t itemid, int value_type, int start
 		zbx_vector_history_record_t *values);
 int	__wrap_zbx_history_add_values(const zbx_vector_ptr_t *history);
 void	__wrap_zbx_history_sql_init(zbx_history_iface_t *hist, unsigned char value_type);
-int	__wrap_zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, char **error);
+int	__wrap_zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, int config_log_slow_queries, char **error);
 void	__wrap_zbx_elastic_version_extract(void);
 int	__wrap_zbx_elastic_version_get(void);
 time_t	__wrap_time(time_t *ptr);
@@ -652,7 +652,7 @@ void	__wrap_zbx_history_sql_init(zbx_history_iface_t *hist, unsigned char value_
 	ZBX_UNUSED(value_type);
 }
 
-int	__wrap_zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, char **error)
+int	__wrap_zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, int config_log_slow_queries, char **error);
 {
 	ZBX_UNUSED(hist);
 	ZBX_UNUSED(value_type);
