diff --git a/cmd/main.go b/cmd/main.go
index 7eb3fac..b026885 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -109,6 +109,9 @@ func Serve(ctx *cli.Context) error {
 
 	certificates.SetupCertificates(mainDomainSuffix, dnsProvider, acmeConfig, acmeUseRateLimits, enableHTTPServer, challengeCache, keyDatabase)
 
+	// TODO: make it graceful
+	go certificates.MaintainCertDB(mainDomainSuffix, dnsProvider, acmeUseRateLimits, keyDatabase)
+
 	if enableHTTPServer {
 		go func() {
 			err := httpServer.ListenAndServe("[::]:80")
diff --git a/server/certificates/certificates.go b/server/certificates/certificates.go
index d2f7c76..e484d78 100644
--- a/server/certificates/certificates.go
+++ b/server/certificates/certificates.go
@@ -444,75 +444,65 @@ func SetupCertificates(mainDomainSuffix []byte, dnsProvider string, acmeConfig *
 			log.Printf("[ERROR] Couldn't renew main domain certificate, continuing with mock certs only: %s", err)
 		}
 	}
-
-	go (func() {
-		for {
-			err := keyDatabase.Sync()
-			if err != nil {
-				log.Printf("[ERROR] Syncing key database failed: %s", err)
-			}
-			time.Sleep(5 * time.Minute)
-			// TODO: graceful exit
-		}
-	})()
-	go (func() {
-		for {
-			// clean up expired certs
-			now := time.Now()
-			expiredCertCount := 0
-			keyDatabaseIterator := keyDatabase.Items()
-			key, resBytes, err := keyDatabaseIterator.Next()
-			for err == nil {
-				if !bytes.Equal(key, mainDomainSuffix) {
-					resGob := bytes.NewBuffer(resBytes)
-					resDec := gob.NewDecoder(resGob)
-					res := &certificate.Resource{}
-					err = resDec.Decode(res)
-					if err != nil {
-						panic(err)
-					}
-
-					tlsCertificates, err := certcrypto.ParsePEMBundle(res.Certificate)
-					if err != nil || !tlsCertificates[0].NotAfter.After(now) {
-						err := keyDatabase.Delete(key)
-						if err != nil {
-							log.Printf("[ERROR] Deleting expired certificate for %s failed: %s", string(key), err)
-						} else {
-							expiredCertCount++
-						}
-					}
-				}
-				key, resBytes, err = keyDatabaseIterator.Next()
-			}
-			log.Printf("[INFO] Removed %d expired certificates from the database", expiredCertCount)
-
-			// compact the database
-			result, err := keyDatabase.Compact()
-			if err != nil {
-				log.Printf("[ERROR] Compacting key database failed: %s", err)
-			} else {
-				log.Printf("[INFO] Compacted key database (%+v)", result)
-			}
-
-			// update main cert
-			res := &certificate.Resource{}
-			if !database.PogrebGet(keyDatabase, mainDomainSuffix, res) {
-				log.Printf("[ERROR] Couldn't renew certificate for main domain: %s", "expected main domain cert to exist, but it's missing - seems like the database is corrupted")
-			} else {
-				tlsCertificates, err := certcrypto.ParsePEMBundle(res.Certificate)
-
-				// renew main certificate 30 days before it expires
-				if !tlsCertificates[0].NotAfter.After(time.Now().Add(-30 * 24 * time.Hour)) {
-					go (func() {
-						_, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(mainDomainSuffix), string(mainDomainSuffix[1:])}, res, "", dnsProvider, mainDomainSuffix, acmeUseRateLimits, keyDatabase)
-						if err != nil {
-							log.Printf("[ERROR] Couldn't renew certificate for main domain: %s", err)
-						}
-					})()
-				}
-			}
-
-			time.Sleep(12 * time.Hour)
-		}
-	})()
+}
+
+func MaintainCertDB(mainDomainSuffix []byte, dnsProvider string, acmeUseRateLimits bool, keyDatabase database.CertDB) {
+	for {
+		// clean up expired certs
+		now := time.Now()
+		expiredCertCount := 0
+		keyDatabaseIterator := keyDatabase.Items()
+		key, resBytes, err := keyDatabaseIterator.Next()
+		for err == nil {
+			if !bytes.Equal(key, mainDomainSuffix) {
+				resGob := bytes.NewBuffer(resBytes)
+				resDec := gob.NewDecoder(resGob)
+				res := &certificate.Resource{}
+				err = resDec.Decode(res)
+				if err != nil {
+					panic(err)
+				}
+
+				tlsCertificates, err := certcrypto.ParsePEMBundle(res.Certificate)
+				if err != nil || !tlsCertificates[0].NotAfter.After(now) {
+					err := keyDatabase.Delete(key)
+					if err != nil {
+						log.Printf("[ERROR] Deleting expired certificate for %s failed: %s", string(key), err)
+					} else {
+						expiredCertCount++
+					}
+				}
+			}
+			key, resBytes, err = keyDatabaseIterator.Next()
+		}
+		log.Printf("[INFO] Removed %d expired certificates from the database", expiredCertCount)
+
+		// compact the database
+		result, err := keyDatabase.Compact()
+		if err != nil {
+			log.Printf("[ERROR] Compacting key database failed: %s", err)
+		} else {
+			log.Printf("[INFO] Compacted key database (%+v)", result)
+		}
+
+		// update main cert
+		res := &certificate.Resource{}
+		if !database.PogrebGet(keyDatabase, mainDomainSuffix, res) {
+			log.Printf("[ERROR] Couldn't renew certificate for main domain: %s", "expected main domain cert to exist, but it's missing - seems like the database is corrupted")
+		} else {
+			tlsCertificates, err := certcrypto.ParsePEMBundle(res.Certificate)
+
+			// renew main certificate 30 days before it expires
+			if !tlsCertificates[0].NotAfter.After(time.Now().Add(-30 * 24 * time.Hour)) {
+				go (func() {
+					_, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(mainDomainSuffix), string(mainDomainSuffix[1:])}, res, "", dnsProvider, mainDomainSuffix, acmeUseRateLimits, keyDatabase)
+					if err != nil {
+						log.Printf("[ERROR] Couldn't renew certificate for main domain: %s", err)
+					}
+				})()
+			}
+		}
+
+		time.Sleep(12 * time.Hour)
+	}
 }