diff --git a/daemon/cookie_cache.c b/daemon/cookie_cache.c
index 1a7aa4d22..4fdbb26e3 100644
--- a/daemon/cookie_cache.c
+++ b/daemon/cookie_cache.c
@@ -8,11 +8,13 @@
 #include "poller.h"
 #include "str.h"
 
-static const char *cookie_in_use = "MAGIC";
-
 INLINE void cookie_cache_state_init(struct cookie_cache_state *s) {
-	s->cookies = g_hash_table_new(str_hash, str_equal);
-	s->chunks = g_string_chunk_new(4 * 1024);
+	s->in_use = g_hash_table_new(str_hash, str_equal);
+	s->cookies = g_hash_table_new_full(str_hash, str_equal, free, free);
+}
+INLINE void cookie_cache_state_cleanup(struct cookie_cache_state *s) {
+	g_hash_table_destroy(s->cookies);
+	g_hash_table_destroy(s->in_use);
 }
 
 void cookie_cache_init(struct cookie_cache *c) {
@@ -27,8 +29,6 @@ void cookie_cache_init(struct cookie_cache *c) {
 static void __cookie_cache_check_swap(struct cookie_cache *c) {
 	if (rtpe_now.tv_sec - c->swap_time >= 30) {
 		g_hash_table_remove_all(c->old.cookies);
-		g_string_chunk_clear(c->old.chunks);
-		swap_ptrs(&c->old.chunks, &c->current.chunks);
 		swap_ptrs(&c->old.cookies, &c->current.cookies);
 		c->swap_time = rtpe_now.tv_sec;
 	}
@@ -46,24 +46,32 @@ restart:
 	if (!ret)
 		ret = g_hash_table_lookup(c->old.cookies, s);
 	if (ret) {
-		if (ret == (void *) cookie_in_use) {
-			/* another thread is working on this right now */
-			cond_wait(&c->cond, &c->lock);
-			goto restart;
-		}
 		ret = str_dup(ret);
 		mutex_unlock(&c->lock);
 		return ret;
 	}
-	g_hash_table_replace(c->current.cookies, (void *) s, (void *) cookie_in_use);
+
+	// is it being worked on right now by another thread?
+	void *p = g_hash_table_lookup(c->current.in_use, s);
+	if (!p)
+		p = g_hash_table_lookup(c->old.in_use, s);
+	if (p) {
+		cond_wait(&c->cond, &c->lock);
+		goto restart;
+	}
+
+	// caller is required to call cookie_cache_insert or cookie_cache_remove
+	// before `s` runs out of scope
+	g_hash_table_replace(c->current.in_use, (void *) s, (void *) 0x1);
 	mutex_unlock(&c->lock);
 	return NULL;
 }
 
 void cookie_cache_insert(struct cookie_cache *c, const str *s, const str *r) {
 	mutex_lock(&c->lock);
-	g_hash_table_replace(c->current.cookies, str_chunk_insert(c->current.chunks, s),
-		str_chunk_insert(c->current.chunks, r));
+	g_hash_table_remove(c->current.in_use, s);
+	g_hash_table_remove(c->old.in_use, s);
+	g_hash_table_replace(c->current.cookies, str_dup(s), str_dup(r));
 	g_hash_table_remove(c->old.cookies, s);
 	cond_broadcast(&c->cond);
 	mutex_unlock(&c->lock);
@@ -71,6 +79,8 @@ void cookie_cache_insert(struct cookie_cache *c, const str *s, const str *r) {
 
 void cookie_cache_remove(struct cookie_cache *c, const str *s) {
 	mutex_lock(&c->lock);
+	g_hash_table_remove(c->current.in_use, s);
+	g_hash_table_remove(c->old.in_use, s);
 	g_hash_table_remove(c->current.cookies, s);
 	g_hash_table_remove(c->old.cookies, s);
 	cond_broadcast(&c->cond);
@@ -78,8 +88,6 @@ void cookie_cache_remove(struct cookie_cache *c, const str *s) {
 }
 
 void cookie_cache_cleanup(struct cookie_cache *c) {
-	g_hash_table_destroy(c->current.cookies);
-	g_hash_table_destroy(c->old.cookies);
-	g_string_chunk_free(c->current.chunks);
-	g_string_chunk_free(c->old.chunks);
+	cookie_cache_state_cleanup(&c->current);
+	cookie_cache_state_cleanup(&c->old);
 }
diff --git a/include/cookie_cache.h b/include/cookie_cache.h
index cc8d5d37d..ff5a8654f 100644
--- a/include/cookie_cache.h
+++ b/include/cookie_cache.h
@@ -7,8 +7,8 @@
 #include "str.h"
 
 struct cookie_cache_state {
+	GHashTable *in_use;
 	GHashTable *cookies;
-	GStringChunk *chunks;
 };
 
 struct cookie_cache {