diff --git a/server/handlers.go b/server/handlers.go
index ef3e9af59e9afba28e54894a064e866f69ee88ca..40621adc925f41e39479519734af659f24b931b3 100644
--- a/server/handlers.go
+++ b/server/handlers.go
@@ -20,6 +20,36 @@ import (
 	"github.com/coreos/dex/storage"
 )
 
+func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
+	start := s.now()
+	err := func() error {
+		// Instead of trying to introspect health, just try to use the underlying storage.
+		a := storage.AuthRequest{
+			ID:       storage.NewID(),
+			ClientID: storage.NewID(),
+
+			// Set a short expiry so if the delete fails this will be cleaned up quickly by garbage collection.
+			Expiry: s.now().Add(time.Minute),
+		}
+
+		if err := s.storage.CreateAuthRequest(a); err != nil {
+			return fmt.Errorf("create auth request: %v", err)
+		}
+		if err := s.storage.DeleteAuthRequest(a.ID); err != nil {
+			return fmt.Errorf("delete auth request: %v", err)
+		}
+		return nil
+	}()
+
+	t := s.now().Sub(start)
+	if err != nil {
+		log.Printf("Storage health check failed: %v", err)
+		http.Error(w, "Health check failed", http.StatusInternalServerError)
+		return
+	}
+	fmt.Fprintf(w, "Health check passed in %s", t)
+}
+
 func (s *Server) handlePublicKeys(w http.ResponseWriter, r *http.Request) {
 	// TODO(ericchiang): Cache this.
 	keys, err := s.storage.GetKeys()
diff --git a/server/server.go b/server/server.go
index 2e3c00af3eee2d94121eaf1c701c83af24029549..6eb16b333c2eabbe67788925b7e04c272d1b69f0 100644
--- a/server/server.go
+++ b/server/server.go
@@ -159,6 +159,7 @@ func newServer(c Config, rotationStrategy rotationStrategy) (*Server, error) {
 	handleFunc("/auth/{connector}", s.handleConnectorLogin)
 	handleFunc("/callback/{connector}", s.handleConnectorCallback)
 	handleFunc("/approval", s.handleApproval)
+	handleFunc("/healthz", s.handleHealth)
 	s.mux = r
 
 	return s, nil