The database connection is managed by pgx’s connection pool:
db/db.go:10-25
var Pool *pgxpool.Poolfunc Connect(databaseURL string) error { var err error Pool, err = pgxpool.New(context.Background(), databaseURL) if err != nil { return fmt.Errorf("unable to connect to database: %w", err) } return Pool.Ping(context.Background())}func Close() { if Pool != nil { Pool.Close() }}
The Pool variable is a global singleton, initialized once at startup and shared across all requests.
type Post struct { ID int `json:"id"` UserID int `json:"user_id"` Title string `json:"title"` Slug string `json:"slug"` Body string `json:"body"` URL *string `json:"url"` CreatedAt time.Time `json:"created_at"` Username string `json:"username"` Points int `json:"points"` CommentCount int `json:"comment_count"` Upvoted bool `json:"-"` Tags []Tag `json:"-"`}
type Comment struct { ID int `json:"id"` PostID int `json:"post_id"` UserID int `json:"user_id"` ParentID *int `json:"parent_id"` Body string `json:"body"` CreatedAt time.Time `json:"created_at"` Username string `json:"username"` Points int `json:"points"` Children []*Comment `json:"-"` Upvoted bool `json:"-"` Depth int `json:"-"`}
func GetPost(ctx context.Context, postID int, currentUserID *int) (*models.Post, error) { query := ` SELECT p.id, p.user_id, p.title, p.slug, p.body, p.url, p.created_at, u.username, u.created_at, COALESCE((SELECT COUNT(*) FROM upvotes WHERE post_id = p.id), 0) as points, COALESCE((SELECT COUNT(*) FROM comments WHERE post_id = p.id), 0) as comment_count, CASE WHEN $2::int IS NOT NULL THEN EXISTS(SELECT 1 FROM upvotes WHERE post_id = p.id AND user_id = $2) ELSE false END as upvoted FROM posts p JOIN users u ON p.user_id = u.id WHERE p.id = $1` // ... scan into post struct}
Key patterns:
Use COALESCE for nullable aggregates
Use EXISTS for boolean checks (faster than COUNT(*) > 0)
Conditional logic with CASE WHEN for per-user data
func getFilteredPosts(ctx context.Context, f PostFilter) ([]models.Post, error) { where, args, argN := buildWhereArgs(f) query := ` SELECT p.id, p.user_id, p.title, p.slug, p.body, p.url, p.created_at, u.username, u.created_at, COALESCE((SELECT COUNT(*) FROM upvotes WHERE post_id = p.id), 0) as points, COALESCE((SELECT COUNT(*) FROM comments WHERE post_id = p.id), 0) as comment_count, CASE WHEN $1::int IS NOT NULL THEN EXISTS(SELECT 1 FROM upvotes WHERE post_id = p.id AND user_id = $1) ELSE false END as upvoted FROM posts p JOIN users u ON p.user_id = u.id` + where + ` ORDER BY p.created_at DESC LIMIT $` + itoa(argN) + ` OFFSET $` + itoa(argN+1) args = append(args, f.Limit, f.Offset) rows, err := Pool.Query(ctx, query, args...) // ... iterate rows}
Dynamic query building:
Build WHERE clauses conditionally based on filters
Use numbered parameters ($1, $2, etc.)
Always use parameterized queries (prevents SQL injection)
Comments are stored flat with parent_id, then built into a tree:
db/comments.go:94-112
func buildCommentTree(comments []*models.Comment) []*models.Comment { byID := make(map[int]*models.Comment) for _, c := range comments { c.Children = []*models.Comment{} byID[c.ID] = c } var roots []*models.Comment for _, c := range comments { if c.ParentID == nil { c.Depth = 0 roots = append(roots, c) } else if parent, ok := byID[*c.ParentID]; ok { c.Depth = parent.Depth + 1 parent.Children = append(parent.Children, c) } } return roots}
CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(64) UNIQUE NOT NULL, password_hash TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());CREATE INDEX idx_users_username ON users(username);
// ❌ Bad (N+1 problem)for _, post := range posts { tags, _ := db.GetTagsForPost(ctx, post.ID) // Query per post post.Tags = tags}// ✅ Good (bulk load)postIDs := getPostIDs(posts)tagsByPostID, _ := db.GetTagsForPosts(ctx, postIDs) // One queryfor i := range posts { posts[i].Tags = tagsByPostID[posts[i].ID]}
See db/roles.go:GetRolesForUsers() for a real example.
-- Index foreign keysCREATE INDEX idx_posts_user_id ON posts(user_id);-- Index sort columnsCREATE INDEX idx_posts_created_at ON posts(created_at DESC);-- Composite indexes for common queriesCREATE INDEX idx_upvotes_post_user ON upvotes(post_id, user_id);
EXPLAIN ANALYZESELECT p.*, COUNT(c.id) as comment_countFROM posts pLEFT JOIN comments c ON c.post_id = p.idGROUP BY p.idORDER BY p.created_at DESCLIMIT 20;