diff --git a/mongoose.c b/mongoose.c
index 1e917340875276be04aba9e10af5db16a9cbd208..d82a3a4709fc15d641cbce8d0cd1a88052f3873b 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -1891,6 +1891,20 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
        (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
 }
 
+void mg_if_timer(struct mg_connection *c, time_t now) {
+  if (c->ev_timer_time > 0 && now >= c->ev_timer_time) {
+    double dnow = now, old_value = c->ev_timer_time;
+    mg_call(c, NULL, MG_EV_TIMER, &dnow);
+    /*
+     * To prevent timer firing all the time, reset the timer after delivery.
+     * However, in case user sets it to new value, do not reset.
+     */
+    if (c->ev_timer_time == old_value) {
+      c->ev_timer_time = 0;
+    }
+  }
+}
+
 void mg_if_poll(struct mg_connection *nc, time_t now) {
   mg_call(nc, NULL, MG_EV_POLL, &now);
 }
@@ -3115,6 +3129,7 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, time_t now) {
   if (!(fd_flags & (_MG_F_FD_CAN_READ | _MG_F_FD_CAN_WRITE))) {
     mg_if_poll(nc, now);
   }
+  mg_if_timer(nc, now);
 
   DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags,
        (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
diff --git a/mongoose.h b/mongoose.h
index 01a44064a79785e73c24cdcfade38d61028f2fce..7cbabe525a449a3e7ec3178f00aa99e8cb84b461 100644
--- a/mongoose.h
+++ b/mongoose.h
@@ -698,6 +698,7 @@ typedef void (*mg_event_handler_t)(struct mg_connection *, int ev, void *);
 #define MG_EV_RECV 3    /* Data has benn received. int *num_bytes */
 #define MG_EV_SEND 4    /* Data has been written to a socket. int *num_bytes */
 #define MG_EV_CLOSE 5   /* Connection is closed. NULL */
+#define MG_EV_TIMER 6   /* now >= conn->ev_timer_time. double * */
 
 /*
  * Mongoose event manager.
@@ -730,6 +731,7 @@ struct mg_connection {
   SSL *ssl;
   SSL_CTX *ssl_ctx;
   time_t last_io_time;              /* Timestamp of the last socket IO */
+  double ev_timer_time;             /* Timestamp of the future MG_EV_TIMER */
   mg_event_handler_t proto_handler; /* Protocol-specific event handler */
   void *proto_data;                 /* Protocol-specific data */
   mg_event_handler_t handler;       /* Event handler function */
@@ -1116,6 +1118,9 @@ void mg_if_recved(struct mg_connection *nc, size_t len);
 /* Deliver a POLL event to the connection. */
 void mg_if_poll(struct mg_connection *nc, time_t now);
 
+/* Deliver a TIMER event to the connection. */
+void mg_if_timer(struct mg_connection *c, time_t now);
+
 /* Perform interface-related cleanup on connection before destruction. */
 void mg_if_destroy_conn(struct mg_connection *nc);