diff --git a/integrations/org_count_test.go b/integrations/org_count_test.go
index a394dba01c..a45d1e81b5 100644
--- a/integrations/org_count_test.go
+++ b/integrations/org_count_test.go
@@ -116,7 +116,10 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca
 			Name: username,
 		}).(*models.User)
 
-		orgs, err := models.GetOrgsByUserID(user.ID, true)
+		orgs, err := models.FindOrgs(models.FindOrgOptions{
+			UserID:         user.ID,
+			IncludePrivate: true,
+		})
 		assert.NoError(t, err)
 
 		calcOrgCounts := map[string]int{}
diff --git a/models/org.go b/models/org.go
index 8e60422ef1..b3e67fb521 100644
--- a/models/org.go
+++ b/models/org.go
@@ -440,24 +440,6 @@ func getUsersWhoCanCreateOrgRepo(e db.Engine, orgID int64) ([]*User, error) {
 		And("team_user.org_id = ?", orgID).Asc("`user`.name").Find(&users)
 }
 
-func getOrgsByUserID(e db.Engine, userID int64, showAll bool) ([]*Organization, error) {
-	orgs := make([]*Organization, 0, 10)
-	sess := e.Where("`org_user`.uid=?", userID)
-	if !showAll {
-		sess = sess.And("`org_user`.is_public=?", true)
-	}
-	return orgs, sess.
-		Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").
-		Asc("`user`.name").
-		Find(&orgs)
-}
-
-// GetOrgsByUserID returns a list of organizations that the given user ID
-// has joined.
-func GetOrgsByUserID(userID int64, showAll bool) ([]*Organization, error) {
-	return getOrgsByUserID(db.GetEngine(db.DefaultContext), userID, showAll)
-}
-
 // MinimalOrg represents a simple orgnization with only needed columns
 type MinimalOrg = Organization
 
@@ -519,6 +501,51 @@ func GetUserOrgsList(user *User) ([]*MinimalOrg, error) {
 	return orgs, nil
 }
 
+// FindOrgOptions finds orgs options
+type FindOrgOptions struct {
+	db.ListOptions
+	UserID         int64
+	IncludePrivate bool
+}
+
+func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder {
+	var cond = builder.Eq{"uid": userID}
+	if !includePrivate {
+		cond["is_public"] = true
+	}
+	return builder.Select("org_id").From("org_user").Where(cond)
+}
+
+func (opts FindOrgOptions) toConds() builder.Cond {
+	var cond = builder.NewCond()
+	if opts.UserID > 0 {
+		cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
+	}
+	if !opts.IncludePrivate {
+		cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
+	}
+	return cond
+}
+
+// FindOrgs returns a list of organizations according given conditions
+func FindOrgs(opts FindOrgOptions) ([]*Organization, error) {
+	orgs := make([]*Organization, 0, 10)
+	sess := db.GetEngine(db.DefaultContext).
+		Where(opts.toConds()).
+		Asc("`user`.name")
+	if opts.Page > 0 && opts.PageSize > 0 {
+		sess.Limit(opts.PageSize, opts.PageSize*(opts.Page-1))
+	}
+	return orgs, sess.Find(&orgs)
+}
+
+// CountOrgs returns total count organizations according options
+func CountOrgs(opts FindOrgOptions) (int64, error) {
+	return db.GetEngine(db.DefaultContext).
+		Where(opts.toConds()).
+		Count(new(User))
+}
+
 func getOwnedOrgsByUserID(sess db.Engine, userID int64) ([]*User, error) {
 	orgs := make([]*User, 0, 10)
 	return orgs, sess.
diff --git a/models/org_test.go b/models/org_test.go
index 10ae877458..805c63300b 100644
--- a/models/org_test.go
+++ b/models/org_test.go
@@ -307,18 +307,31 @@ func TestIsPublicMembership(t *testing.T) {
 	test(unittest.NonexistentID, unittest.NonexistentID, false)
 }
 
-func TestGetOrgsByUserID(t *testing.T) {
+func TestFindOrgs(t *testing.T) {
 	assert.NoError(t, unittest.PrepareTestDatabase())
 
-	orgs, err := GetOrgsByUserID(4, true)
+	orgs, err := FindOrgs(FindOrgOptions{
+		UserID:         4,
+		IncludePrivate: true,
+	})
 	assert.NoError(t, err)
 	if assert.Len(t, orgs, 1) {
 		assert.EqualValues(t, 3, orgs[0].ID)
 	}
 
-	orgs, err = GetOrgsByUserID(4, false)
+	orgs, err = FindOrgs(FindOrgOptions{
+		UserID:         4,
+		IncludePrivate: false,
+	})
 	assert.NoError(t, err)
 	assert.Len(t, orgs, 0)
+
+	total, err := CountOrgs(FindOrgOptions{
+		UserID:         4,
+		IncludePrivate: true,
+	})
+	assert.NoError(t, err)
+	assert.EqualValues(t, 1, total)
 }
 
 func TestGetOwnedOrgsByUserID(t *testing.T) {
diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go
index bbf127f891..f539662d62 100644
--- a/routers/api/v1/org/org.go
+++ b/routers/api/v1/org/org.go
@@ -12,7 +12,6 @@ import (
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
-	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/modules/web"
 	"code.gitea.io/gitea/routers/api/v1/user"
 	"code.gitea.io/gitea/routers/api/v1/utils"
@@ -20,25 +19,31 @@ import (
 )
 
 func listUserOrgs(ctx *context.APIContext, u *models.User) {
-
 	listOptions := utils.GetListOptions(ctx)
 	showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == u.ID)
 
-	orgs, err := models.GetOrgsByUserID(u.ID, showPrivate)
+	var opts = models.FindOrgOptions{
+		ListOptions:    listOptions,
+		UserID:         u.ID,
+		IncludePrivate: showPrivate,
+	}
+	orgs, err := models.FindOrgs(opts)
 	if err != nil {
-		ctx.Error(http.StatusInternalServerError, "GetOrgsByUserID", err)
+		ctx.Error(http.StatusInternalServerError, "FindOrgs", err)
+		return
+	}
+	maxResults, err := models.CountOrgs(opts)
+	if err != nil {
+		ctx.Error(http.StatusInternalServerError, "CountOrgs", err)
 		return
 	}
-
-	maxResults := len(orgs)
-	orgs, _ = util.PaginateSlice(orgs, listOptions.Page, listOptions.PageSize).([]*models.Organization)
 
 	apiOrgs := make([]*api.Organization, len(orgs))
 	for i := range orgs {
 		apiOrgs[i] = convert.ToOrganization(orgs[i])
 	}
 
-	ctx.SetLinkHeader(maxResults, listOptions.PageSize)
+	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 	ctx.SetTotalCountHeader(int64(maxResults))
 	ctx.JSON(http.StatusOK, &apiOrgs)
 }
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 72d36761da..9d0b4e3c15 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -167,9 +167,12 @@ func Profile(ctx *context.Context) {
 
 	showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID)
 
-	orgs, err := models.GetOrgsByUserID(ctxUser.ID, showPrivate)
+	orgs, err := models.FindOrgs(models.FindOrgOptions{
+		UserID:         ctxUser.ID,
+		IncludePrivate: showPrivate,
+	})
 	if err != nil {
-		ctx.ServerError("GetOrgsByUserIDDesc", err)
+		ctx.ServerError("FindOrgs", err)
 		return
 	}
 
diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go
index d7aa3264c5..36fe45df04 100644
--- a/routers/web/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
@@ -214,12 +214,34 @@ func DeleteAvatar(ctx *context.Context) {
 func Organization(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("settings")
 	ctx.Data["PageIsSettingsOrganization"] = true
-	orgs, err := models.GetOrgsByUserID(ctx.User.ID, ctx.IsSigned)
+
+	opts := models.FindOrgOptions{
+		ListOptions: db.ListOptions{
+			PageSize: setting.UI.Admin.UserPagingNum,
+			Page:     ctx.FormInt("page"),
+		},
+		UserID:         ctx.User.ID,
+		IncludePrivate: ctx.IsSigned,
+	}
+
+	if opts.Page <= 0 {
+		opts.Page = 1
+	}
+
+	orgs, err := models.FindOrgs(opts)
 	if err != nil {
-		ctx.ServerError("GetOrgsByUserID", err)
+		ctx.ServerError("FindOrgs", err)
+		return
+	}
+	total, err := models.CountOrgs(opts)
+	if err != nil {
+		ctx.ServerError("CountOrgs", err)
 		return
 	}
 	ctx.Data["Orgs"] = orgs
+	pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5)
+	pager.SetDefaultParams(ctx)
+	ctx.Data["Page"] = pager
 	ctx.HTML(http.StatusOK, tplSettingsOrganization)
 }
 
diff --git a/templates/user/settings/organization.tmpl b/templates/user/settings/organization.tmpl
index 3bab1c8957..1689c1b9e2 100644
--- a/templates/user/settings/organization.tmpl
+++ b/templates/user/settings/organization.tmpl
@@ -29,6 +29,7 @@
 					</div>
 					{{end}}
 				</div>
+				{{template "base/paginate" .}}
 			{{else}}
 				{{.i18n.Tr "settings.orgs_none"}}
 			{{end}}