diff --git a/lib/context.c b/lib/context.c
index e11af4532394257316c446fecd92712f97495813..09785706549ad17ebf3d1649a236594d7fd6fa3f 100644
--- a/lib/context.c
+++ b/lib/context.c
@@ -798,6 +798,10 @@ lws_create_context(struct lws_context_creation_info *info)
 	else
 		context->pt_serv_buf_size = 4096;
 
+#if defined(LWS_WITH_ESP32)
+	context->last_free_heap = esp_get_free_heap_size();
+#endif
+
 	/* default to just the platform fops implementation */
 
 	context->fops_platform.LWS_FOP_OPEN	= _lws_plat_file_open;
diff --git a/lib/lws-plat-esp32.c b/lib/lws-plat-esp32.c
index 48688e71951aa8bf4de19cdc2b7d22ef4ef4c837..2ba065b326f66911d4cfa39eea10b0c8bc6d8e89 100644
--- a/lib/lws-plat-esp32.c
+++ b/lib/lws-plat-esp32.c
@@ -117,6 +117,22 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 	pt = &context->pt[tsi];
 	lws_stats_atomic_bump(context, pt, LWSSTATS_C_SERVICE_ENTRY, 1);
 
+	{
+		unsigned long m = lws_now_secs();
+
+		if (m > context->time_last_state_dump) {
+			context->time_last_state_dump = m;
+			n = esp_get_free_heap_size();
+			if (n != context->last_free_heap) {
+				if (n > context->last_free_heap)
+					lwsl_info(" heap :%d (+%d)\n", n, n - context->last_free_heap);
+				else
+					lwsl_info(" heap :%d (-%d)\n", n, context->last_free_heap - n);
+				context->last_free_heap = n;
+			}
+		}
+	}
+
 	if (timeout_ms < 0)
 		goto faked_service;
 
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index ee2edd36635170da95bef52a122d98b2ee2c7d1d..715d60b128f2cd7049005efab4348b1cfec20154 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -998,6 +998,10 @@ struct lws_context {
 	uint64_t last_dump;
 	int updated;
 #endif
+#if defined(LWS_WITH_ESP32)
+	unsigned long time_last_state_dump;
+	uint32_t last_free_heap;
+#endif
 
 	int max_fds;
 #if defined(LWS_USE_LIBEV) || defined(LWS_USE_LIBUV) || defined(LWS_USE_LIBEVENT)