diff --git a/models/issues/comment.go b/models/issues/comment.go
index 901958dc5..8e06838f7 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -349,7 +349,7 @@ func (c *Comment) LoadPoster(ctx context.Context) (err error) {
 	c.Poster, err = user_model.GetPossibleUserByID(ctx, c.PosterID)
 	if err != nil {
 		if user_model.IsErrUserNotExist(err) {
-			c.PosterID = -1
+			c.PosterID = user_model.GhostUserID
 			c.Poster = user_model.NewGhostUser()
 		} else {
 			log.Error("getUserByID[%d]: %v", c.ID, err)
diff --git a/models/issues/issue.go b/models/issues/issue.go
index 6d9c8727b..8655b9de3 100644
--- a/models/issues/issue.go
+++ b/models/issues/issue.go
@@ -219,7 +219,7 @@ func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
 	if issue.Poster == nil && issue.PosterID != 0 {
 		issue.Poster, err = user_model.GetPossibleUserByID(ctx, issue.PosterID)
 		if err != nil {
-			issue.PosterID = -1
+			issue.PosterID = user_model.GhostUserID
 			issue.Poster = user_model.NewGhostUser()
 			if !user_model.IsErrUserNotExist(err) {
 				return fmt.Errorf("getUserByID.(poster) [%d]: %w", issue.PosterID, err)
diff --git a/models/issues/pull.go b/models/issues/pull.go
index 971ce049c..2379c6197 100644
--- a/models/issues/pull.go
+++ b/models/issues/pull.go
@@ -272,7 +272,7 @@ func (pr *PullRequest) LoadAttributes(ctx context.Context) (err error) {
 	if pr.HasMerged && pr.Merger == nil {
 		pr.Merger, err = user_model.GetUserByID(ctx, pr.MergerID)
 		if user_model.IsErrUserNotExist(err) {
-			pr.MergerID = -1
+			pr.MergerID = user_model.GhostUserID
 			pr.Merger = user_model.NewGhostUser()
 		} else if err != nil {
 			return fmt.Errorf("getUserByID [%d]: %w", pr.MergerID, err)
diff --git a/models/user/avatar.go b/models/user/avatar.go
index 8c9abecbe..c6937d7b5 100644
--- a/models/user/avatar.go
+++ b/models/user/avatar.go
@@ -58,8 +58,7 @@ func GenerateRandomAvatar(ctx context.Context, u *User) error {
 
 // AvatarLinkWithSize returns a link to the user's avatar with size. size <= 0 means default size
 func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
-	if u.ID == -1 {
-		// ghost user
+	if u.IsGhost() {
 		return avatars.DefaultAvatarLink()
 	}
 
diff --git a/models/user/user.go b/models/user/user.go
index 60aa6b9a6..ce0e055b1 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -933,7 +933,7 @@ func GetUserByIDs(ctx context.Context, ids []int64) ([]*User, error) {
 // GetPossibleUserByID returns the user if id > 0 or return system usrs if id < 0
 func GetPossibleUserByID(ctx context.Context, id int64) (*User, error) {
 	switch id {
-	case -1:
+	case GhostUserID:
 		return NewGhostUser(), nil
 	case ActionsUserID:
 		return NewActionsUser(), nil
@@ -949,7 +949,7 @@ func GetPossibleUserByIDs(ctx context.Context, ids []int64) ([]*User, error) {
 	uniqueIDs := container.SetOf(ids...)
 	users := make([]*User, 0, len(ids))
 	_ = uniqueIDs.Remove(0)
-	if uniqueIDs.Remove(-1) {
+	if uniqueIDs.Remove(GhostUserID) {
 		users = append(users, NewGhostUser())
 	}
 	if uniqueIDs.Remove(ActionsUserID) {
diff --git a/models/user/user_system.go b/models/user/user_system.go
index f54f4e3ff..612cdb2ca 100644
--- a/models/user/user_system.go
+++ b/models/user/user_system.go
@@ -9,12 +9,18 @@ import (
 	"code.gitea.io/gitea/modules/structs"
 )
 
+const (
+	GhostUserID        = -1
+	GhostUserName      = "Ghost"
+	GhostUserLowerName = "ghost"
+)
+
 // NewGhostUser creates and returns a fake user for someone has deleted their account.
 func NewGhostUser() *User {
 	return &User{
-		ID:        -1,
-		Name:      "Ghost",
-		LowerName: "ghost",
+		ID:        GhostUserID,
+		Name:      GhostUserName,
+		LowerName: GhostUserLowerName,
 	}
 }
 
@@ -23,13 +29,13 @@ func (u *User) IsGhost() bool {
 	if u == nil {
 		return false
 	}
-	return u.ID == -1 && u.Name == "Ghost"
+	return u.ID == GhostUserID && u.Name == GhostUserName
 }
 
 // NewReplaceUser creates and returns a fake user for external user
 func NewReplaceUser(name string) *User {
 	return &User{
-		ID:        -1,
+		ID:        0,
 		Name:      name,
 		LowerName: strings.ToLower(name),
 	}
diff --git a/routers/web/user/avatar.go b/routers/web/user/avatar.go
index 01df2fd29..772cc38be 100644
--- a/routers/web/user/avatar.go
+++ b/routers/web/user/avatar.go
@@ -27,7 +27,7 @@ func AvatarByUserName(ctx *context.Context) {
 	size := int(ctx.ParamsInt64(":size"))
 
 	var user *user_model.User
-	if strings.ToLower(userName) != "ghost" {
+	if strings.ToLower(userName) != user_model.GhostUserLowerName {
 		var err error
 		if user, err = user_model.GetUserByName(ctx, userName); err != nil {
 			if user_model.IsErrUserNotExist(err) {