diff --git a/server/db/adapter.go b/server/db/adapter.go
index 3462d79d9b3525ef89c4c2f94121a86469e6c74b..2a036b1bbefdff8604bd106157d0f58b2b23719c 100644
--- a/server/db/adapter.go
+++ b/server/db/adapter.go
@@ -141,10 +141,10 @@ type Adapter interface {
 
 	// Search
 
-	// FindUsers searches for new contacts given a list of tags
-	FindUsers(user t.Uid, req [][]string, opt []string) ([]t.Subscription, error)
-	// FindTopics searches for group topics given a list of tags
-	FindTopics(req [][]string, opt []string) ([]t.Subscription, error)
+	// FindUsers searches for new contacts given a list of tags.
+	FindUsers(user t.Uid, req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error)
+	// FindTopics searches for group topics given a list of tags.
+	FindTopics(req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error)
 
 	// Messages
 
diff --git a/server/db/mongodb/adapter.go b/server/db/mongodb/adapter.go
index 4aa2c27b610c690aaa4731729dd207840be876c8..c0405add89f3e5cdf54ae256d781f9cffc78e5d6 100644
--- a/server/db/mongodb/adapter.go
+++ b/server/db/mongodb/adapter.go
@@ -2054,7 +2054,7 @@ func (a *adapter) subsDelete(ctx context.Context, filter b.M, hard bool) error {
 }
 
 // Search
-func (a *adapter) getFindPipeline(req [][]string, opt []string) (map[string]struct{}, b.A) {
+func (a *adapter) getFindPipeline(req [][]string, opt []string, activeOnly bool) (map[string]struct{}, b.A) {
 	allReq := t.FlattenDoubleSlice(req)
 	index := make(map[string]struct{})
 	var allTags []interface{}
@@ -2063,11 +2063,12 @@ func (a *adapter) getFindPipeline(req [][]string, opt []string) (map[string]stru
 		index[tag] = struct{}{}
 	}
 
+	matchOn := b.M{"tags": b.M{"$in": allTags}}
+	if activeOnly {
+		matchOn["state"] = b.M{"$eq": t.StateOK}
+	}
 	pipeline := b.A{
-		b.M{"$match": b.M{
-			"tags":  b.M{"$in": allTags},
-			"state": b.M{"$ne": t.StateDeleted},
-		}},
+		b.M{"$match": matchOn},
 
 		b.M{"$project": b.M{"_id": 1, "access": 1, "createdat": 1, "updatedat": 1, "public": 1, "trusted": 1, "tags": 1}},
 
@@ -2104,8 +2105,8 @@ func (a *adapter) getFindPipeline(req [][]string, opt []string) (map[string]stru
 }
 
 // FindUsers searches for new contacts given a list of tags
-func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscription, error) {
-	index, pipeline := a.getFindPipeline(req, opt)
+func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error) {
+	index, pipeline := a.getFindPipeline(req, opt, activeOnly)
 	cur, err := a.db.Collection("users").Aggregate(a.ctx, pipeline)
 	if err != nil {
 		return nil, err
@@ -2143,8 +2144,8 @@ func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscr
 }
 
 // FindTopics searches for group topics given a list of tags
-func (a *adapter) FindTopics(req [][]string, opt []string) ([]t.Subscription, error) {
-	index, pipeline := a.getFindPipeline(req, opt)
+func (a *adapter) FindTopics(req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error) {
+	index, pipeline := a.getFindPipeline(req, opt, activeOnly)
 	cur, err := a.db.Collection("topics").Aggregate(a.ctx, pipeline)
 	if err != nil {
 		return nil, err
diff --git a/server/db/mysql/adapter.go b/server/db/mysql/adapter.go
index ae4f4e1daecbda5ec4c2da6173741a73ea8fa636..1700e1973e97c1d1107faf048644b159de9a30ae 100644
--- a/server/db/mysql/adapter.go
+++ b/server/db/mysql/adapter.go
@@ -2341,10 +2341,14 @@ func (a *adapter) SubsDelForUser(user t.Uid, hard bool) error {
 
 // Returns a list of users who match given tags, such as "email:jdoe@example.com" or "tel:+18003287448".
 // Searching the 'users.Tags' for the given tags using respective index.
-func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscription, error) {
+func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error) {
 	index := make(map[string]struct{})
 	var args []interface{}
-	args = append(args, t.StateOK)
+	stateConstraint := ""
+	if activeOnly {
+		args = append(args, t.StateOK)
+		stateConstraint = "u.state=? AND "
+	}
 	allReq := t.FlattenDoubleSlice(req)
 	for _, tag := range append(allReq, opt...) {
 		args = append(args, tag)
@@ -2353,7 +2357,7 @@ func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscr
 
 	query := "SELECT u.id,u.createdat,u.updatedat,u.access,u.public,u.trusted,u.tags,COUNT(*) AS matches " +
 		"FROM users AS u LEFT JOIN usertags AS t ON t.userid=u.id " +
-		"WHERE u.state=? AND t.tag IN (?" + strings.Repeat(",?", len(allReq)+len(opt)-1) + ") " +
+		"WHERE " + stateConstraint + "t.tag IN (?" + strings.Repeat(",?", len(allReq)+len(opt)-1) + ") " +
 		"GROUP BY u.id,u.createdat,u.updatedat,u.access,u.public,u.trusted,u.tags "
 	if len(allReq) > 0 {
 		query += "HAVING"
@@ -2429,10 +2433,14 @@ func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscr
 
 // Returns a list of topics with matching tags.
 // Searching the 'topics.Tags' for the given tags using respective index.
-func (a *adapter) FindTopics(req [][]string, opt []string) ([]t.Subscription, error) {
+func (a *adapter) FindTopics(req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error) {
 	index := make(map[string]struct{})
 	var args []interface{}
-	args = append(args, t.StateOK)
+	stateConstraint := ""
+	if activeOnly {
+		args = append(args, t.StateOK)
+		stateConstraint = "u.state=? AND "
+	}
 	var allReq []string
 	for _, el := range req {
 		allReq = append(allReq, el...)
@@ -2444,7 +2452,7 @@ func (a *adapter) FindTopics(req [][]string, opt []string) ([]t.Subscription, er
 
 	query := "SELECT t.name AS topic,t.createdat,t.updatedat,t.usebt,t.access,t.public,t.trusted,t.tags,COUNT(*) AS matches " +
 		"FROM topics AS t LEFT JOIN topictags AS tt ON t.name=tt.topic " +
-		"WHERE t.state=? AND tt.tag IN (?" + strings.Repeat(",?", len(allReq)+len(opt)-1) + ") " +
+		"WHERE " + stateConstraint + "tt.tag IN (?" + strings.Repeat(",?", len(allReq)+len(opt)-1) + ") " +
 		"GROUP BY t.name,t.createdat,t.updatedat,t.usebt,t.access,t.public,t.trusted,t.tags "
 	if len(allReq) > 0 {
 		query += "HAVING"
diff --git a/server/db/rethinkdb/adapter.go b/server/db/rethinkdb/adapter.go
index 6429856fd8b2a5ceceddb9e948641f5bb09cac7b..31dc3ee6a25d52ef437b5dc817254a843af795bf 100644
--- a/server/db/rethinkdb/adapter.go
+++ b/server/db/rethinkdb/adapter.go
@@ -1863,7 +1863,7 @@ func (a *adapter) subsDelForUser(user t.Uid, hard bool) error {
 
 // FindUsers returns a list of users who match given tags, such as "email:jdoe@example.com" or "tel:+18003287448".
 // Searching the 'users.Tags' for the given tags using respective index.
-func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscription, error) {
+func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error) {
 	index := make(map[string]struct{})
 	allReq := t.FlattenDoubleSlice(req)
 	var allTags []interface{}
@@ -1888,9 +1888,11 @@ func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscr
 	// Get users matched by tags, sort by number of matches from high to low.
 	query := rdb.DB(a.dbName).
 		Table("users").
-		GetAllByIndex("Tags", allTags...).
-		Filter(rdb.Row.Field("State").Eq(t.StateOK)).
-		Pluck("Id", "Access", "CreatedAt", "UpdatedAt", "Public", "Trusted", "Tags").
+		GetAllByIndex("Tags", allTags...)
+	if activeOnly {
+		query = query.Filter(rdb.Row.Field("State").Eq(t.StateOK))
+	}
+	query = query.Pluck("Id", "Access", "CreatedAt", "UpdatedAt", "Public", "Trusted", "Tags").
 		Group("Id").
 		Ungroup().
 		Map(func(row rdb.Term) rdb.Term {
@@ -1948,7 +1950,7 @@ func (a *adapter) FindUsers(uid t.Uid, req [][]string, opt []string) ([]t.Subscr
 
 // FindTopics returns a list of topics with matching tags.
 // Searching the 'topics.Tags' for the given tags using respective index.
-func (a *adapter) FindTopics(req [][]string, opt []string) ([]t.Subscription, error) {
+func (a *adapter) FindTopics(req [][]string, opt []string, activeOnly bool) ([]t.Subscription, error) {
 	index := make(map[string]struct{})
 	var allReq []string
 	for _, el := range req {
@@ -1961,9 +1963,11 @@ func (a *adapter) FindTopics(req [][]string, opt []string) ([]t.Subscription, er
 	}
 	query := rdb.DB(a.dbName).
 		Table("topics").
-		GetAllByIndex("Tags", allTags...).
-		Filter(rdb.Row.Field("State").Eq(t.StateOK)).
-		Pluck("Id", "Access", "CreatedAt", "UpdatedAt", "UseBt", "Public", "Trusted", "Tags").
+		GetAllByIndex("Tags", allTags...)
+	if activeOnly {
+		query = query.Filter(rdb.Row.Field("State").Eq(t.StateOK))
+	}
+	query = query.Pluck("Id", "Access", "CreatedAt", "UpdatedAt", "UseBt", "Public", "Trusted", "Tags").
 		Group("Id").
 		Ungroup().
 		Map(func(row rdb.Term) rdb.Term {
diff --git a/server/store/mock_store/mock_store.go b/server/store/mock_store/mock_store.go
index 2ff2af1c49a22bdfe2026c6d3b7261628de02c21..14945d18d20c5da9e6983be166cca5c1a355a2f9 100644
--- a/server/store/mock_store/mock_store.go
+++ b/server/store/mock_store/mock_store.go
@@ -415,18 +415,18 @@ func (mr *MockUsersPersistenceInterfaceMockRecorder) FailCred(id, method interfa
 }
 
 // FindSubs mocks base method.
-func (m *MockUsersPersistenceInterface) FindSubs(id types.Uid, required [][]string, optional []string) ([]types.Subscription, error) {
+func (m *MockUsersPersistenceInterface) FindSubs(id types.Uid, required [][]string, optional []string, activeOnly bool) ([]types.Subscription, error) {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FindSubs", id, required, optional)
+	ret := m.ctrl.Call(m, "FindSubs", id, required, optional, activeOnly)
 	ret0, _ := ret[0].([]types.Subscription)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
 
 // FindSubs indicates an expected call of FindSubs.
-func (mr *MockUsersPersistenceInterfaceMockRecorder) FindSubs(id, required, optional interface{}) *gomock.Call {
+func (mr *MockUsersPersistenceInterfaceMockRecorder) FindSubs(id, required, optional, activeOnly interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindSubs", reflect.TypeOf((*MockUsersPersistenceInterface)(nil).FindSubs), id, required, optional)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindSubs", reflect.TypeOf((*MockUsersPersistenceInterface)(nil).FindSubs), id, required, optional, activeOnly)
 }
 
 // Get mocks base method.
diff --git a/server/store/store.go b/server/store/store.go
index b0aab5caf3930f6d216c077f5269a918bf946d64..114764c653552b08be422179114b96cd808e8c1d 100644
--- a/server/store/store.go
+++ b/server/store/store.go
@@ -266,7 +266,7 @@ type UsersPersistenceInterface interface {
 	UpdateTags(uid types.Uid, add, remove, reset []string) ([]string, error)
 	UpdateState(uid types.Uid, state types.ObjState) error
 	GetSubs(id types.Uid) ([]types.Subscription, error)
-	FindSubs(id types.Uid, required [][]string, optional []string) ([]types.Subscription, error)
+	FindSubs(id types.Uid, required [][]string, optional []string, activeOnly bool) ([]types.Subscription, error)
 	GetTopics(id types.Uid, opts *types.QueryOpt) ([]types.Subscription, error)
 	GetTopicsAny(id types.Uid, opts *types.QueryOpt) ([]types.Subscription, error)
 	GetOwnTopics(id types.Uid) ([]string, error)
@@ -424,12 +424,12 @@ func (usersMapper) GetSubs(id types.Uid) ([]types.Subscription, error) {
 // `required` specifies an AND of ORs for required terms:
 // at least one element of every sublist in `required` must be present in the object's tags list.
 // `optional` specifies a list of optional terms.
-func (usersMapper) FindSubs(id types.Uid, required [][]string, optional []string) ([]types.Subscription, error) {
-	usubs, err := adp.FindUsers(id, required, optional)
+func (usersMapper) FindSubs(id types.Uid, required [][]string, optional []string, activeOnly bool) ([]types.Subscription, error) {
+	usubs, err := adp.FindUsers(id, required, optional, activeOnly)
 	if err != nil {
 		return nil, err
 	}
-	tsubs, err := adp.FindTopics(required, optional)
+	tsubs, err := adp.FindTopics(required, optional, activeOnly)
 	if err != nil {
 		return nil, err
 	}
diff --git a/server/topic.go b/server/topic.go
index 48355e39871d3fb1106befedf9d1cad8fad13523..44609b977f93abf9088efdb287f5b05ac45b1167 100644
--- a/server/topic.go
+++ b/server/topic.go
@@ -2419,8 +2419,7 @@ func (t *Topic) replyGetSub(sess *Session, asUid types.Uid, authLevel auth.Level
 							return errors.New("attempt to search by restricted tags")
 						}
 
-						// TODO: allow root to find suspended users and topics.
-						subs, err = store.Users.FindSubs(asUid, req, opt)
+						subs, err = store.Users.FindSubs(asUid, req, opt, sess.authLvl == auth.LevelRoot)
 						if err != nil {
 							sess.queueOut(decodeStoreErrorExplicitTs(err, id, msg.Original, now, incomingReqTs, nil))
 							return err