diff --git a/Makefile b/Makefile
index 2f758ea022b162d48ec386a5aa9f9583f1658d71..883d600b186d788a0dc5fc39fb8c80cc074914cc 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ get-build-deps:
 getdeps:
 	@mkdir -p ${GOPATH}/bin
 	@which golangci-lint 1>/dev/null || (echo "Installing golangci-lint" && curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.27.0)
-	@which ruleguard 1>/dev/null || (echo "Installing ruleguard" && GO111MODULE=off go get github.com/quasilyte/go-ruleguard/...)
+	@which ruleguard 1>/dev/null || (echo "Installing ruleguard" && go get github.com/quasilyte/go-ruleguard/cmd/ruleguard@v0.2.1)
 
 tools/bin/revive: tools/check/go.mod
 	cd tools/check; \
@@ -82,7 +82,7 @@ else
 	@${GOPATH}/bin/ruleguard -rules ruleguard.rules.go ./tests/go/...
 endif
 
-verifiers: getdeps cppcheck fmt static-check
+verifiers: getdeps cppcheck fmt static-check ruleguard
 
 # Builds various components locally.
 build-go: build-cpp get-rocksdb
diff --git a/build/docker/env/cpu/ubuntu18.04/Dockerfile b/build/docker/env/cpu/ubuntu18.04/Dockerfile
index 2a9a42e9bed338ae835c6e22ae3cb5a93afbb002..2815f2000cfc909eed9fbe2f85523d1e3a74379e 100644
--- a/build/docker/env/cpu/ubuntu18.04/Dockerfile
+++ b/build/docker/env/cpu/ubuntu18.04/Dockerfile
@@ -40,7 +40,7 @@ ENV PATH $GOPATH/bin:$GOROOT/bin:$PATH
 RUN mkdir -p /usr/local/go && wget -qO- "https://golang.org/dl/go1.15.2.linux-amd64.tar.gz" | tar --strip-components=1 -xz -C /usr/local/go && \
     mkdir -p "$GOPATH/src" "$GOPATH/bin" && \
     curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ${GOPATH}/bin v1.27.0 && \
-    export GO111MODULE=off && go get github.com/quasilyte/go-ruleguard/... && \
+    export GO111MODULE=on && go get github.com/quasilyte/go-ruleguard/cmd/ruleguard@v0.2.1 && \
     chmod -R 777 "$GOPATH" && chmod -R a+w $(go env GOTOOLDIR)
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
diff --git a/internal/proxy/task.go b/internal/proxy/task.go
index bd2251a2d851b729548c1f92376fd4779730298c..ba7a853c20b8e0b09bfed3d58e81fe16abeb83b1 100644
--- a/internal/proxy/task.go
+++ b/internal/proxy/task.go
@@ -572,7 +572,7 @@ func (qt *QueryTask) PostExecute() error {
 							continue
 						}
 						distance := hits[q][i].Scores[loc]
-						if distance > maxDistance || (distance == maxDistance && choice != q) {
+						if distance > maxDistance || (math.Abs(float64(distance-maxDistance)) < math.SmallestNonzeroFloat32 && choice != q) {
 							choice = q
 							maxDistance = distance
 							valid = true
diff --git a/ruleguard.rules.go b/ruleguard.rules.go
index 3ed15287e9ed00f748d5a5057ef49ffe6fb687bf..cf566e2f52e3fb02c107cbc1b76c70d2dc24a616 100644
--- a/ruleguard.rules.go
+++ b/ruleguard.rules.go
@@ -46,6 +46,7 @@ func unconvert(m fluent.Matcher) {
 func timeeq(m fluent.Matcher) {
 	m.Match("$t0 == $t1").Where(m["t0"].Type.Is("time.Time")).Report("using == with time.Time")
 	m.Match("$t0 != $t1").Where(m["t0"].Type.Is("time.Time")).Report("using != with time.Time")
+	m.Match(`map[$k]$v`).Where(m["k"].Type.Is("time.Time")).Report("map with time.Time keys are easy to misuse")
 }
 
 // Wrong err in error check
@@ -213,10 +214,13 @@ func ifreturn(m fluent.Matcher) {
 func oddifsequence(m fluent.Matcher) {
 	/*
 		m.Match("if $x { $*_ }; if $x {$*_ }").Report("odd sequence of if test")
+
 		m.Match("if $x == $y { $*_ }; if $y == $x {$*_ }").Report("odd sequence of if tests")
 		m.Match("if $x != $y { $*_ }; if $y != $x {$*_ }").Report("odd sequence of if tests")
+
 		m.Match("if $x < $y { $*_ }; if $y > $x {$*_ }").Report("odd sequence of if tests")
 		m.Match("if $x <= $y { $*_ }; if $y >= $x {$*_ }").Report("odd sequence of if tests")
+
 		m.Match("if $x > $y { $*_ }; if $y < $x {$*_ }").Report("odd sequence of if tests")
 		m.Match("if $x >= $y { $*_ }; if $y <= $x {$*_ }").Report("odd sequence of if tests")
 	*/
@@ -357,7 +361,7 @@ func largeloopcopy(m fluent.Matcher) {
 	m.Match(
 		`for $_, $v := range $_ { $*_ }`,
 	).
-		Where(m["v"].Type.Size > 512).
+		Where(m["v"].Type.Size > 1024).
 		Report(`loop copies large value each iteration`)
 }
 
@@ -454,3 +458,20 @@ func hmacnew(m fluent.Matcher) {
 	).Where(m["x"].Pure).
 		Report("invalid hash passed to hmac.New()")
 }
+
+func writestring(m fluent.Matcher) {
+	m.Match(`io.WriteString($w, string($b))`).
+		Where(m["b"].Type.Is("[]byte")).
+		Suggest("$w.Write($b)")
+}
+
+func badlock(m fluent.Matcher) {
+	// Shouldn't give many false positives without type filter
+	// as Lock+Unlock pairs in combination with defer gives us pretty
+	// a good chance to guess correctly. If we constrain the type to sync.Mutex
+	// then it'll be harder to match embedded locks and custom methods
+	// that may forward the call to the sync.Mutex (or other synchronization primitive).
+
+	m.Match(`$mu.Lock(); defer $mu.RUnlock()`).Report(`maybe $mu.RLock() was intended?`)
+	m.Match(`$mu.RLock(); defer $mu.Unlock()`).Report(`maybe $mu.Lock() was intended?`)
+}
\ No newline at end of file