diff --git a/src/knot/server/net.c b/src/knot/server/net.c
index b3054d08666db51b0f166d4040263ebc9bb6283e..a55cb89d7433c743548254b1eacea93dee8845b7 100644
--- a/src/knot/server/net.c
+++ b/src/knot/server/net.c
@@ -81,6 +81,11 @@ int net_bound_socket(int type, struct sockaddr_storage *ss)
 	int flag = 1;
 	(void) setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
 
+	/* Reuse port if available. */
+#if defined(SO_REUSEPORT)
+	(void) setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag));
+#endif
+
 	/* Unlink UNIX socket if exists. */
 	if (ss->ss_family == AF_UNIX) {
 		unlink(addr_str);
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index 28d4b03719ac8a9c5f2a60078935891d7cba940b..fb94e127ef4f5cac9dbc0056028778da0b48b9f5 100644
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -449,6 +449,30 @@ void __attribute__ ((constructor)) udp_master_init()
 #endif /* HAVE_RECVMMSG */
 }
 
+static void unbind_ifaces(ifacelist_t *ifaces, fd_set *set, int maxfd)
+{
+	ref_release((ref_t *)ifaces);
+#if defined(SO_REUSEPORT)
+	for (int fd = 0; fd <= maxfd; ++fd) {
+		if (FD_ISSET(fd, set)) {
+			close(fd);
+		}
+	}
+#endif
+	FD_ZERO(set);
+}
+
+static int bind_iface(iface_t *iface, fd_set *set)
+{
+#if defined(SO_REUSEPORT)
+	int fd = net_bound_socket(SOCK_DGRAM, &iface->addr);
+#else
+	int fd = iface->fd[IO_UDP];
+#endif
+	FD_SET(fd, set);
+	return fd;
+}
+
 int udp_master(dthread_t *thread)
 {
 	unsigned cpu = dt_online_cpus();
@@ -497,18 +521,16 @@ int udp_master(dthread_t *thread)
 		/* Check handler state. */
 		if (knot_unlikely(*iostate & ServerReload)) {
 			*iostate &= ~ServerReload;
-			maxfd = 0;
-			minfd = INT_MAX;
-			FD_ZERO(&fds);
 
 			rcu_read_lock();
-			ref_release((ref_t *)ref);
+			unbind_ifaces(ref, &fds, maxfd);
+			maxfd = 0;
+			minfd = INT_MAX;
 			ref = handler->server->ifaces;
 			if (ref) {
 				iface_t *i = NULL;
 				WALK_LIST(i, ref->l) {
-					int fd = i->fd[IO_UDP];
-					FD_SET(fd, &fds);
+					int fd = bind_iface(i, &fds);
 					maxfd = MAX(fd, maxfd);
 					minfd = MIN(fd, minfd);
 				}
@@ -544,7 +566,7 @@ int udp_master(dthread_t *thread)
 	}
 
 	_udp_deinit(rq);
-	ref_release((ref_t *)ref);
+	unbind_ifaces(ref, &fds, maxfd);
 	mp_delete(udp.query_ctx.mm.ctx);
 	return KNOT_EOK;
 }