diff --git a/lib/ngtcp2_cc.c b/lib/ngtcp2_cc.c
index 072cbed087b90440b567484844a1b684eba31652..82fcf70c3c6923d3bfaba11c3dccdcc5fad744c1 100644
--- a/lib/ngtcp2_cc.c
+++ b/lib/ngtcp2_cc.c
@@ -31,6 +31,12 @@
 #include "ngtcp2_mem.h"
 #include "ngtcp2_rcvry.h"
 
+uint64_t ngtcp2_cc_compute_initcwnd(size_t max_packet_size) {
+  uint64_t n = 2 * max_packet_size;
+  n = ngtcp2_max(n, 14720);
+  return ngtcp2_min(10 * max_packet_size, n);
+}
+
 ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
                                   size_t pktlen, ngtcp2_tstamp ts_sent) {
   pkt->pkt_num = pkt_num;
@@ -95,6 +101,10 @@ void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
     return;
   }
 
+  if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) {
+    return;
+  }
+
   if (cstat->cwnd < cstat->ssthresh) {
     cstat->cwnd += pkt->pktlen;
     ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
@@ -150,7 +160,8 @@ void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
   if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) {
     target_cwnd =
         cc->max_delivery_rate_sec * cstat->min_rtt * 289 / NGTCP2_SECONDS / 100;
-    min_cwnd = 2 * cstat->max_packet_size;
+
+    min_cwnd = ngtcp2_cc_compute_initcwnd(cstat->max_packet_size) * 289 / 100;
     cc->target_cwnd = ngtcp2_max(min_cwnd, target_cwnd);
 
     ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
@@ -233,6 +244,10 @@ void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
     return;
   }
 
+  if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) {
+    return;
+  }
+
   if (cstat->cwnd < cstat->ssthresh) {
     /* slow-start */
     cstat->cwnd += pkt->pktlen;
@@ -362,7 +377,7 @@ void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
     target_cwnd =
         cc->max_delivery_rate_sec * cstat->min_rtt * 289 / NGTCP2_SECONDS / 100;
 
-    min_cwnd = 2 * cstat->max_packet_size;
+    min_cwnd = ngtcp2_cc_compute_initcwnd(cstat->max_packet_size) * 289 / 100;
     cc->target_cwnd = ngtcp2_max(min_cwnd, target_cwnd);
 
     ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
diff --git a/lib/ngtcp2_cc.h b/lib/ngtcp2_cc.h
index c606d8543f1ff4bc5c4978963360cfbe0139793a..9fbeaac3e8b6e87b72cadb32b126a34ea238a6d9 100644
--- a/lib/ngtcp2_cc.h
+++ b/lib/ngtcp2_cc.h
@@ -37,6 +37,11 @@
 struct ngtcp2_log;
 typedef struct ngtcp2_log ngtcp2_log;
 
+/*
+ * ngtcp2_cc_compute_initcwnd computes initial cwnd.
+ */
+uint64_t ngtcp2_cc_compute_initcwnd(size_t max_packet_size);
+
 ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
                                   size_t pktlen, ngtcp2_tstamp ts_sent);
 
diff --git a/lib/ngtcp2_conn.c b/lib/ngtcp2_conn.c
index 32deb41cb3a6ad85fcf140ef412fbf45fdc754c0..4c51c7af62b8bb178cf2faf088d2bfd9d242ca3d 100644
--- a/lib/ngtcp2_conn.c
+++ b/lib/ngtcp2_conn.c
@@ -514,8 +514,6 @@ static int ts_retired_less(const ngtcp2_pq_entry *lhs,
 }
 
 static void conn_reset_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) {
-  uint64_t cwnd, min_cwnd;
-
   memset(cstat, 0, sizeof(*cstat));
   cstat->smoothed_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
   cstat->rttvar = NGTCP2_DEFAULT_INITIAL_RTT / 2;
@@ -524,9 +522,7 @@ static void conn_reset_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) {
   memset(cstat->last_tx_pkt_ts, 0xff, sizeof(cstat->last_tx_pkt_ts));
   memset(cstat->loss_time, 0xff, sizeof(cstat->loss_time));
   cstat->max_packet_size = conn->local.settings.max_packet_size;
-  min_cwnd = 2 * cstat->max_packet_size;
-  cwnd = ngtcp2_max(min_cwnd, 14720);
-  cstat->cwnd = ngtcp2_min(10 * cstat->max_packet_size, cwnd);
+  cstat->cwnd = ngtcp2_cc_compute_initcwnd(cstat->max_packet_size);
   cstat->ssthresh = UINT64_MAX;
 }
 
@@ -1228,7 +1224,7 @@ static uint64_t conn_cwnd_is_zero(ngtcp2_conn *conn) {
   uint64_t bytes_in_flight = conn->cstat.bytes_in_flight;
   uint64_t cwnd =
       conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)
-          ? /* min_cwnd = */ 2 * conn->cstat.max_packet_size
+          ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_packet_size)
           : conn->cstat.cwnd;
 
   return bytes_in_flight >= cwnd;
@@ -8888,7 +8884,7 @@ void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
                             ngtcp2_duration ack_delay) {
   ngtcp2_conn_stat *cstat = &conn->cstat;
 
-  rtt = ngtcp2_max(rtt, NGTCP2_NANOSECONDS);
+  rtt = ngtcp2_max(rtt, NGTCP2_GRANULARITY);
 
   cstat->latest_rtt = rtt;
 
diff --git a/lib/ngtcp2_rtb.c b/lib/ngtcp2_rtb.c
index b2ce59a9b1c2e97acceb2e326a7985068385c43f..e1c08d60b89e2d4c0a396a869fae5da1b54bcf4b 100644
--- a/lib/ngtcp2_rtb.c
+++ b/lib/ngtcp2_rtb.c
@@ -446,6 +446,9 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
           ngtcp2_conn_update_rtt(conn, pkt_ts - largest_pkt_sent_ts,
                                  fr->ack_delay_unscaled);
         }
+
+        ngtcp2_rst_on_ack_recv(rtb->rst, cstat);
+        cc->on_ack_recv(cc, cstat, ts);
         rtb_on_pkt_acked(rtb, ent, cstat, ts);
         /* At this point, it is invalided because rtb->ents might be
            modified. */
@@ -483,6 +486,9 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
           ngtcp2_conn_update_rtt(conn, pkt_ts - largest_pkt_sent_ts,
                                  fr->ack_delay_unscaled);
         }
+
+        ngtcp2_rst_on_ack_recv(rtb->rst, cstat);
+        cc->on_ack_recv(cc, cstat, ts);
         rtb_on_pkt_acked(rtb, ent, cstat, ts);
       }
       rtb_remove(rtb, &it, ent, cstat);
@@ -492,11 +498,6 @@ ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
     ++i;
   }
 
-  if (conn) {
-    ngtcp2_rst_on_ack_recv(rtb->rst, cstat);
-    cc->on_ack_recv(cc, cstat, ts);
-  }
-
   return num_acked;
 }