diff --git a/database/contexts/query_target.c b/database/contexts/query_target.c
index e2e36a11ea..0c08dffd70 100644
--- a/database/contexts/query_target.c
+++ b/database/contexts/query_target.c
@@ -1052,7 +1052,7 @@ QUERY_TARGET *query_target_create(QUERY_TARGET_REQUEST *qtr) {
     if(query_target_has_percentage_of_group(qt))
         qt->window.options &= ~RRDR_OPTION_PERCENTAGE;
 
-    rrdr_relative_window_to_absolute(&qt->window.after, &qt->window.before, &qt->window.now);
+    qt->internal.relative = rrdr_relative_window_to_absolute(&qt->window.after, &qt->window.before, &qt->window.now);
 
     // prepare our local variables - we need these across all these functions
     QUERY_TARGET_LOCALS qtl = {
diff --git a/database/contexts/rrdcontext.h b/database/contexts/rrdcontext.h
index 829a4f2b33..7c0c156737 100644
--- a/database/contexts/rrdcontext.h
+++ b/database/contexts/rrdcontext.h
@@ -409,6 +409,7 @@ typedef struct query_target {
     struct {
         SPINLOCK spinlock;
         bool used;                              // when true, this query is currently being used
+        bool relative;                          // when true, this query uses relative timestamps
         size_t queries;                         // how many query we have done so far with this QUERY_TARGET - not related to database queries
         struct query_target *prev;
         struct query_target *next;
diff --git a/libnetdata/buffer/buffer.c b/libnetdata/buffer/buffer.c
index b437628633..e775b95176 100644
--- a/libnetdata/buffer/buffer.c
+++ b/libnetdata/buffer/buffer.c
@@ -15,6 +15,7 @@ void buffer_reset(BUFFER *wb) {
     wb->options = 0;
     wb->date = 0;
     wb->expires = 0;
+    buffer_no_cacheable(wb);
 
     buffer_overflow_check(wb);
 }
@@ -254,6 +255,7 @@ BUFFER *buffer_create(size_t size, size_t *statistics)
     b->size = size;
     b->content_type = CT_TEXT_PLAIN;
     b->statistics = statistics;
+    buffer_no_cacheable(b);
     buffer_overflow_init(b);
     buffer_overflow_check(b);
 
@@ -317,6 +319,7 @@ void buffer_json_initialize(BUFFER *wb, const char *key_quote, const char *value
         buffer_fast_strcat(wb, "{", 1);
 
     wb->content_type = CT_APPLICATION_JSON;
+    buffer_no_cacheable(wb);
 }
 
 void buffer_json_finalize(BUFFER *wb) {
diff --git a/web/api/badges/web_buffer_svg.c b/web/api/badges/web_buffer_svg.c
index 2ea41e6688..e4f7a37657 100644
--- a/web/api/badges/web_buffer_svg.c
+++ b/web/api/badges/web_buffer_svg.c
@@ -1057,8 +1057,10 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
             buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
             w->response.data->date = now_realtime_sec();
             w->response.data->expires = w->response.data->date + refresh;
+            buffer_cacheable(w->response.data);
         }
-        else buffer_no_cacheable(w->response.data);
+        else
+            buffer_no_cacheable(w->response.data);
 
         if(!value_color) {
             switch(rc->status) {
diff --git a/web/api/queries/weights.c b/web/api/queries/weights.c
index a59c756505..3c2e0826e1 100644
--- a/web/api/queries/weights.c
+++ b/web/api/queries/weights.c
@@ -1808,6 +1808,8 @@ int web_api_v12_weights(BUFFER *wb, QUERY_WEIGHTS_REQUEST *qwr) {
 
     if(!rrdr_relative_window_to_absolute(&qwr->after, &qwr->before, NULL))
         buffer_no_cacheable(wb);
+    else
+        buffer_cacheable(wb);
 
     if (qwr->before <= qwr->after) {
         resp = HTTP_RESP_BAD_REQUEST;
diff --git a/web/api/web_api.c b/web/api/web_api.c
index 9a3f308eec..1737204136 100644
--- a/web/api/web_api.c
+++ b/web/api/web_api.c
@@ -32,6 +32,8 @@ static bool web_client_check_acl_and_bearer(struct web_client *w, WEB_CLIENT_ACL
 }
 
 int web_client_api_request_vX(RRDHOST *host, struct web_client *w, char *url_path_endpoint, struct web_api_command *api_commands) {
+    buffer_no_cacheable(w->response.data);
+
     if(unlikely(!url_path_endpoint || !*url_path_endpoint)) {
         buffer_flush(w->response.data);
         buffer_sprintf(w->response.data, "Which API command?");
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 33564cd6c2..d98ebdecfd 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -883,6 +883,11 @@ static inline int web_client_api_request_v1_data(RRDHOST *host, struct web_clien
     else if(format == DATASOURCE_JSONP)
         buffer_strcat(w->response.data, ");");
 
+    if(qt->internal.relative)
+        buffer_no_cacheable(w->response.data);
+    else
+        buffer_cacheable(w->response.data);
+
 cleanup:
     query_target_release(qt);
     onewayalloc_destroy(owa);
diff --git a/web/api/web_api_v2.c b/web/api/web_api_v2.c
index 067c1368c6..c49e762866 100644
--- a/web/api/web_api_v2.c
+++ b/web/api/web_api_v2.c
@@ -629,6 +629,11 @@ static int web_client_api_request_v2_data(RRDHOST *host __maybe_unused, struct w
     else if(format == DATASOURCE_JSONP)
         buffer_strcat(w->response.data, ");");
 
+    if(qt->internal.relative)
+        buffer_no_cacheable(w->response.data);
+    else
+        buffer_cacheable(w->response.data);
+
 cleanup:
     query_target_release(qt);
     onewayalloc_destroy(owa);
diff --git a/web/rtc/webrtc.c b/web/rtc/webrtc.c
index cc99d5200d..331326c84f 100644
--- a/web/rtc/webrtc.c
+++ b/web/rtc/webrtc.c
@@ -304,7 +304,7 @@ static void webrtc_execute_api_request(WEBRTC_DC *chan, const char *request, siz
     web_client_timeout_checkpoint_set(w, 0);
     web_client_decode_path_and_query_string(w, path);
     path = (char *)buffer_tostring(w->url_path_decoded);
-    w->response.code = (short)web_client_api_request_with_node_selection(localhost, w, path);
+    w->response.code = (short)web_client_api_request_with_node_selection(rrdb.localhost, w, path);
     web_client_timeout_checkpoint_response_ready(w, NULL);
 
     size_t sent_bytes = 0;
diff --git a/web/server/web_client.c b/web/server/web_client.c
index e9d9def972..0d8e5616fc 100644
--- a/web/server/web_client.c
+++ b/web/server/web_client.c
@@ -1274,12 +1274,9 @@ void web_client_build_http_header(struct web_client *w) {
         w->response.data->date = now_realtime_sec();
 
     // set a proper expiration date, if not already set
-    if(unlikely(!w->response.data->expires)) {
-        if(w->response.data->options & WB_CONTENT_NO_CACHEABLE)
-            w->response.data->expires = w->response.data->date + rrdb.localhost->update_every;
-        else
-            w->response.data->expires = w->response.data->date + 86400;
-    }
+    if(unlikely(!w->response.data->expires))
+        w->response.data->expires = w->response.data->date +
+                ((w->response.data->options & WB_CONTENT_NO_CACHEABLE) ? 0 : 86400);
 
     // prepare the HTTP response header
     netdata_log_debug(D_WEB_CLIENT, "%llu: Generating HTTP header with response %d.", w->id, w->response.code);