diff --git a/src/lib-dict/dict-redis.c b/src/lib-dict/dict-redis.c
index 6aa3824..4d38212 100644
--- a/src/lib-dict/dict-redis.c
+++ b/src/lib-dict/dict-redis.c
@@ -30,6 +30,7 @@ enum redis_input_state {
 struct redis_connection {
 	struct connection conn;
 	struct redis_dict *dict;
+	struct timeout *to_idle;
 
 	string_t *last_reply;
 	unsigned int bytes_left;
@@ -46,7 +47,7 @@ struct redis_dict_reply {
 struct redis_dict {
 	struct dict dict;
 	char *username, *key_prefix, *expire_value;
-	unsigned int timeout_msecs, db_id;
+	unsigned int timeout_msecs, idle_timeout_msecs, db_id;
 
 	struct ioloop *ioloop, *prev_ioloop;
 	struct redis_connection conn;
@@ -108,6 +109,8 @@ static void redis_conn_destroy(struct connection *_conn)
 	array_clear(&conn->dict->replies);
 	array_clear(&conn->dict->input_states);
 
+	if (conn->to_idle != NULL)
+		timeout_remove(&conn->to_idle);
 	if (conn->dict->ioloop != NULL)
 		io_loop_stop(conn->dict->ioloop);
 }
@@ -134,6 +137,8 @@ static void redis_wait(struct redis_dict *dict)
 		io_loop_run(dict->ioloop);
 	} while (array_count(&dict->input_states) > 0);
 
+	if (dict->conn.to_idle != NULL)
+		timeout_reset(dict->conn.to_idle);
 	timeout_remove(&to);
 	io_loop_set_current(dict->prev_ioloop);
 	connection_switch_ioloop(&dict->conn.conn);
@@ -283,11 +288,22 @@ static void redis_conn_input(struct connection *_conn)
 static void redis_conn_connected(struct connection *_conn, bool success)
 {
 	struct redis_connection *conn = (struct redis_connection *)_conn;
+	struct ioloop *cur_ioloop = current_ioloop;
 
 	if (!success) {
 		i_error("redis: connect(%s) failed: %m", _conn->name);
 	} else {
 		conn->dict->connected = TRUE;
+		if (conn->dict->idle_timeout_msecs > 0) {
+			i_assert(conn->to_idle == NULL);
+			/* add this to main ioloop in case we're now waiting
+			   in a new ioloop */
+			if (conn->dict->prev_ioloop != NULL)
+				io_loop_set_current(conn->dict->prev_ioloop);
+			conn->to_idle = timeout_add(conn->dict->idle_timeout_msecs,
+						    redis_conn_destroy, _conn);
+			io_loop_set_current(cur_ioloop);
+		}
 	}
 	if (conn->dict->ioloop != NULL)
 		io_loop_stop(conn->dict->ioloop);
@@ -390,6 +406,12 @@ redis_dict_init(struct dict *driver, const char *uri,
 					"Invalid timeout_msecs: %s", *args+14);
 				ret = -1;
 			}
+		} else if (strncmp(*args, "idle_timeout_msecs=", 19) == 0) {
+			if (str_to_uint(*args+19, &dict->idle_timeout_msecs) < 0) {
+				*error_r = t_strdup_printf(
+					"Invalid idle_timeout_msecs: %s", *args+19);
+				ret = -1;
+			}
 		} else {
 			*error_r = t_strdup_printf("Unknown parameter: %s",
 						   *args);
@@ -433,6 +455,7 @@ static void redis_dict_deinit(struct dict *_dict)
 		i_assert(dict->connected);
 		redis_wait(dict);
 	}
+	redis_conn_destroy(&dict->conn.conn);
 	connection_deinit(&dict->conn.conn);
 	str_free(&dict->conn.last_reply);
 	array_free(&dict->replies);
@@ -532,6 +555,8 @@ redis_dict_lookup_real(struct redis_dict *dict, pool_t pool,
 		timeout_remove(&to);
 	}
 
+	if (dict->conn.to_idle != NULL)
+		timeout_reset(dict->conn.to_idle);
 	io_loop_set_current(dict->prev_ioloop);
 	connection_switch_ioloop(&dict->conn.conn);
 	io_loop_set_current(dict->ioloop);
