Skip to content

Table of Contents

Bookstore REST API

A production-shaped CRUD REST API in Go — the Month 4 (web + databases) project.

level Go db module

Overview

A REST API for managing authors and books, built with idiomatic net/http + chi, persisted in PostgreSQL via pgx, with versioned migrations, request validation, structured logging, and a clean layered architecture (handler → service → repository). Full brief in SPEC.md.

⚠️ This is its own Go module (it needs third-party libraries and a running database). It is intentionally excluded from the repo's root CI. To build/run it: go mod tidy + a Postgres instance.

Architecture

flowchart LR
    client[Client] -->|HTTP/JSON| R[chi router + middleware]
    R --> H[handler]
    H --> S[service<br/>business rules + validation]
    S --> Repo[repository interface]
    Repo --> PG[(PostgreSQL via pgx)]

Dependencies point inward: handlers know HTTP, repositories know SQL, and the service in the middle knows neither — only domain models and the repository interface.

Tech Stack

Go · chi (routing/middleware) · pgx (Postgres) · golang-migrate (migrations) · log/slog (logging) · httptest + table-driven tests · Docker

Getting Started

cd projects/03-rest-api-bookstore
cp .env.example .env          # set DATABASE_URL etc.
go mod tidy                   # resolve dependencies

# start Postgres (example)
docker run --rm -d --name bookstore-db -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres:16

make migrate-up               # apply migrations/
make run                      # or: go run ./cmd/api

API

Method Path Description
GET /healthz liveness
GET /v1/books list (pagination/filter)
POST /v1/books create
GET /v1/books/{id} fetch one
PUT /v1/books/{id} update
DELETE /v1/books/{id} delete
GET/POST /v1/authors authors CRUD

Project Layout

cmd/api/                 composition root + graceful shutdown
internal/book/           handler, service, repository, model
internal/author/         handler, service, repository, model
internal/middleware/     request logging, recovery, request IDs
internal/httperr/        consistent JSON error responses
internal/validate/       input validation
internal/platform/postgres/  connection pool + migrations
internal/config/         env-driven configuration
migrations/              golang-migrate SQL (up/down)
db/queries/              SQL (sqlc-style)

Testing Strategy

Table-driven unit tests for services (against a fake repository) and handlers (httptest). Integration tests run against a real Postgres via testcontainers-go (require Docker) — see SPEC.

Lessons Learned

  • Where to put validation (service vs handler) and how to map domain errors → HTTP status codes consistently.
  • Connection-pool sizing and threading context deadlines into every query.

Future Improvements

  • sqlc-generated queries; OpenAPI spec; JWT auth; cursor pagination; rate limiting.

🎒 Portfolio

Résumé bullets:

  • "Designed and shipped a layered REST API in Go (chi, pgx, PostgreSQL, golang-migrate) with request validation, structured logging, consistent error handling, and httptest + testcontainers tests."

Interview talking points: layered/hexagonal boundaries; repository pattern + interface seams for testing; migrations strategy; mapping domain errors to status codes; pool tuning.


Projects · Repo README