diff --git a/caddyhttp/proxy/policy.go b/caddyhttp/proxy/policy.go
index 96e382a5c..0bf657cae 100644
--- a/caddyhttp/proxy/policy.go
+++ b/caddyhttp/proxy/policy.go
@@ -2,7 +2,7 @@ package proxy
 
 import (
 	"math/rand"
-	"sync/atomic"
+	"sync"
 )
 
 // HostPool is a collection of UpstreamHosts.
@@ -82,20 +82,22 @@ func (r *LeastConn) Select(pool HostPool) *UpstreamHost {
 
 // RoundRobin is a policy that selects hosts based on round robin ordering.
 type RoundRobin struct {
-	Robin uint32
+	robin uint32
+	mutex sync.Mutex
 }
 
 // Select selects an up host from the pool using a round robin ordering scheme.
 func (r *RoundRobin) Select(pool HostPool) *UpstreamHost {
 	poolLen := uint32(len(pool))
-	selection := atomic.AddUint32(&r.Robin, 1) % poolLen
-	host := pool[selection]
-	// if the currently selected host is not available, just ffwd to up host
-	for i := uint32(1); !host.Available() && i < poolLen; i++ {
-		host = pool[(selection+i)%poolLen]
+	r.mutex.Lock()
+	defer r.mutex.Unlock()
+	// Return next available host
+	for i := uint32(0); i < poolLen; i++ {
+		r.robin++
+		host := pool[r.robin%poolLen]
+		if host.Available() {
+			return host
+		}
 	}
-	if !host.Available() {
-		return nil
-	}
-	return host
+	return nil
 }
diff --git a/caddyhttp/proxy/policy_test.go b/caddyhttp/proxy/policy_test.go
index 4cc05f029..4ef591195 100644
--- a/caddyhttp/proxy/policy_test.go
+++ b/caddyhttp/proxy/policy_test.go
@@ -63,11 +63,18 @@ func TestRoundRobinPolicy(t *testing.T) {
 	if h != pool[2] {
 		t.Error("Expected to skip down host.")
 	}
-	// mark host as full
-	pool[2].Conns = 1
-	pool[2].MaxConns = 1
+	// mark host as up
+	pool[1].Unhealthy = false
+
 	h = rrPolicy.Select(pool)
-	if h != pool[0] {
+	if h == pool[2] {
+		t.Error("Expected to balance evenly among healthy hosts")
+	}
+	// mark host as full
+	pool[1].Conns = 1
+	pool[1].MaxConns = 1
+	h = rrPolicy.Select(pool)
+	if h != pool[2] {
 		t.Error("Expected to skip full host.")
 	}
 }