diff --git a/app/dns/server.go b/app/dns/server.go
index ba273b53..2972ff5c 100644
--- a/app/dns/server.go
+++ b/app/dns/server.go
@@ -11,6 +11,7 @@ import (
 	"v2ray.com/core"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
+	"v2ray.com/core/common/signal"
 )
 
 const (
@@ -37,6 +38,7 @@ type Server struct {
 	hosts   map[string]net.IP
 	records map[string]*DomainRecord
 	servers []NameServer
+	task    *signal.PeriodicTask
 }
 
 func New(ctx context.Context, config *Config) (*Server, error) {
@@ -45,6 +47,13 @@ func New(ctx context.Context, config *Config) (*Server, error) {
 		servers: make([]NameServer, len(config.NameServers)),
 		hosts:   config.GetInternalHosts(),
 	}
+	server.task = &signal.PeriodicTask{
+		Interval: time.Minute * 10,
+		Execute: func() error {
+			server.cleanup()
+			return nil
+		},
+	}
 	v := core.FromContext(ctx)
 	if v == nil {
 		return nil, newError("V is not in context.")
@@ -75,16 +84,14 @@ func New(ctx context.Context, config *Config) (*Server, error) {
 	return server, nil
 }
 
-func (*Server) Interface() interface{} {
-	return (*Server)(nil)
-}
-
+// Start implements common.Runnable.
 func (s *Server) Start() error {
-	return nil
+	return s.task.Start()
 }
 
-func (*Server) Close() error {
-	return nil
+// Close implements common.Runnable.
+func (s *Server) Close() error {
+	return s.task.Close()
 }
 
 func (s *Server) GetCached(domain string) []net.IP {
@@ -98,18 +105,12 @@ func (s *Server) GetCached(domain string) []net.IP {
 	return nil
 }
 
-func (s *Server) tryCleanup() {
+func (s *Server) cleanup() {
 	s.Lock()
 	defer s.Unlock()
 
-	if len(s.records) > 256 {
-		domains := make([]string, 0, 256)
-		for d, r := range s.records {
-			if r.Expired() {
-				domains = append(domains, d)
-			}
-		}
-		for _, d := range domains {
+	for d, r := range s.records {
+		if r.Expired() {
 			delete(s.records, d)
 		}
 	}
@@ -126,8 +127,6 @@ func (s *Server) LookupIP(domain string) ([]net.IP, error) {
 		return ips, nil
 	}
 
-	s.tryCleanup()
-
 	for _, server := range s.servers {
 		response := server.QueryA(domain)
 		select {