diff --git a/backend/main.go b/backend/main.go
index 8a2d36f939208136a7b5b3a7778310c95e0080bb..0b3dd2bac5870e20a5a2d9a5e4c3fafc79bc34ca 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -53,14 +53,15 @@ func main() {
 		Handler: metricsMux,
 	}
 
-	go func() {
+	runner := shared.Runner{}
+	runner.RunParallel(func() {
 		if err := metrics.ListenAndServe(); err != nil && err != http.ErrServerClosed {
 			log.Printf("error in metrics server: %s", err.Error())
 		}
 		log.Printf("metrics shut down, shutting down asynq as well")
 		srv.Shutdown()
-	}()
-	go func() {
+	})
+	runner.RunParallel(func() {
 		if err := srv.Run(mux); err != nil {
 			log.Printf("error in asynq server: %s", err.Error())
 		}
@@ -68,5 +69,6 @@ func main() {
 		if err := metrics.Shutdown(context.Background()); err != nil {
 			log.Printf("error shutting down metrics server: %s", err.Error())
 		}
-	}()
+	})
+	runner.Wait()
 }
diff --git a/shared/runner.go b/shared/runner.go
new file mode 100644
index 0000000000000000000000000000000000000000..172004035693002fed17e375ff84156bf3719938
--- /dev/null
+++ b/shared/runner.go
@@ -0,0 +1,19 @@
+package shared
+
+import "sync"
+
+type Runner struct {
+	wg sync.WaitGroup
+}
+
+func (runner *Runner) RunParallel(closure func()) {
+	runner.wg.Add(1)
+	go func() {
+		closure()
+		runner.wg.Done()
+	}()
+}
+
+func (runner *Runner) Wait() {
+	runner.wg.Wait()
+}