diff --git a/plugin/cache/cache.go b/plugin/cache/cache.go
index bc82bb604..69de55f17 100644
--- a/plugin/cache/cache.go
+++ b/plugin/cache/cache.go
@@ -163,6 +163,9 @@ func (w *ResponseWriter) WriteMsg(res *dns.Msg) error {
 	var duration time.Duration
 	if mt == response.NameError || mt == response.NoData {
 		duration = computeTTL(msgTTL, w.minnttl, w.nttl)
+	} else if mt == response.ServerError {
+		// use default ttl which is 5s
+		duration = minTTL
 	} else {
 		duration = computeTTL(msgTTL, w.minpttl, w.pttl)
 	}
@@ -206,7 +209,7 @@ func (w *ResponseWriter) set(m *dns.Msg, key uint64, mt response.Type, duration
 		i := newItem(m, w.now(), duration)
 		w.pcache.Add(key, i)
 
-	case response.NameError, response.NoData:
+	case response.NameError, response.NoData, response.ServerError:
 		i := newItem(m, w.now(), duration)
 		w.ncache.Add(key, i)
 
diff --git a/plugin/cache/cache_test.go b/plugin/cache/cache_test.go
index 790dce7fb..7c65bca64 100644
--- a/plugin/cache/cache_test.go
+++ b/plugin/cache/cache_test.go
@@ -87,6 +87,34 @@ var cacheTestCases = []cacheTestCase{
 		},
 		shouldCache: true,
 	},
+	{
+		RecursionAvailable: true, Authoritative: false,
+		Case: test.Case{
+			Rcode: dns.RcodeServerFailure,
+			Qname: "example.org.", Qtype: dns.TypeA,
+			Ns: []dns.RR{},
+		},
+		in: test.Case{
+			Rcode: dns.RcodeServerFailure,
+			Qname: "example.org.", Qtype: dns.TypeA,
+			Ns: []dns.RR{},
+		},
+		shouldCache: true,
+	},
+	{
+		RecursionAvailable: true, Authoritative: false,
+		Case: test.Case{
+			Rcode: dns.RcodeNotImplemented,
+			Qname: "example.org.", Qtype: dns.TypeA,
+			Ns: []dns.RR{},
+		},
+		in: test.Case{
+			Rcode: dns.RcodeNotImplemented,
+			Qname: "example.org.", Qtype: dns.TypeA,
+			Ns: []dns.RR{},
+		},
+		shouldCache: true,
+	},
 	{
 		RecursionAvailable: true, Authoritative: true,
 		Case: test.Case{
diff --git a/plugin/pkg/response/typify.go b/plugin/pkg/response/typify.go
index 9faa17d7b..f4dd91fa4 100644
--- a/plugin/pkg/response/typify.go
+++ b/plugin/pkg/response/typify.go
@@ -15,6 +15,8 @@ const (
 	NoError Type = iota
 	// NameError is a NXDOMAIN in header, SOA in auth.
 	NameError
+	// ServerError is a set of errors we want to cache, for now it containers SERVFAIL and NOTIMPL.
+	ServerError
 	// NoData indicates name found, but not the type: NOERROR in header, SOA in auth.
 	NoData
 	// Delegation is a msg with a pointer to another nameserver: NOERROR in header, NS in auth, optionally fluff in additional (not checked).
@@ -28,13 +30,14 @@ const (
 )
 
 var toString = map[Type]string{
-	NoError:    "NOERROR",
-	NameError:  "NXDOMAIN",
-	NoData:     "NODATA",
-	Delegation: "DELEGATION",
-	Meta:       "META",
-	Update:     "UPDATE",
-	OtherError: "OTHERERROR",
+	NoError:     "NOERROR",
+	NameError:   "NXDOMAIN",
+	ServerError: "SERVERERROR",
+	NoData:      "NODATA",
+	Delegation:  "DELEGATION",
+	Meta:        "META",
+	Update:      "UPDATE",
+	OtherError:  "OTHERERROR",
 }
 
 func (t Type) String() string { return toString[t] }
@@ -106,6 +109,10 @@ func Typify(m *dns.Msg, t time.Time) (Type, *dns.OPT) {
 		return NameError, opt
 	}
 
+	if m.Rcode == dns.RcodeServerFailure || m.Rcode == dns.RcodeNotImplemented {
+		return ServerError, opt
+	}
+
 	if ns > 0 && m.Rcode == dns.RcodeSuccess {
 		return Delegation, opt
 	}