Project ⏱ 5 min read

08 · File Structure

Navigating the lp-coupon-api and lp-reward-store-api repos

lp-coupon-api Layout

lp-coupon-api/ ├── main.go ← entry point, app wiring, graceful shutdown ├── go.mod ← dependency list (like package.json) ├── go.sum ← dependency lock (like package-lock.json) ├── Makefile ← dev commands: make run, make test, make build ├── Dockerfile ├── docker-compose.yml ├── config/ │ └── config.go ← Viper config loading from env vars ├── database/ │ └── connection.go ← GORM connection manager with retry logic ├── internal/ ← private: cannot be imported by external packages │ ├── handlers/ ← HTTP layer: parse request, call service, format response │ ├── services/ ← Business logic layer │ ├── repository/ ← Data access layer (GORM queries) │ │ └── interfaces.go ← All repo contracts defined here │ ├── models/ ← GORM entity structs (Coupon, UserCoupon, ...) │ ├── middleware/ ← Fiber middleware: auth, logging, rate limit, pagination │ ├── clients/ ← External HTTP clients (ECI), Redis, Kafka │ ├── routes/ │ │ └── routes.go ← Dependency injection + route registration │ └── constants/ ← Error codes, status enums ├── pkg/ ← Public reusable utilities (can be imported externally) │ ├── logger/ ← Structured logger wrapper │ ├── zlog/ ← Low-level zerolog interface used in services/repos │ ├── retryer/ ← Configurable retry with backoff or fixed delay │ ├── ratelimit/ ← Redis-backed rate limit key helpers │ ├── helpers/ ← Cache key builder, misc utilities │ ├── pagination/ ← Pagination parameter parsing │ └── context/ ← Context helpers: get client, trace ID, user ID ├── scripts/ │ └── migration/ ← SQL migration files + migrate.sh runner └── tests/ ← Integration tests

The internal/ Rule

Go enforces that code in internal/ can only be imported by code in the parent directory tree. It is not accessible to external packages or other repos. Use it for everything that is specific to this service.

pkg/ has no such restriction — it is meant for utilities that could theoretically be shared (logger, retryer, helpers).

Where to Add New Code

What you're adding Where it goes
New API endpointinternal/handlers/ + wire in routes/routes.go
Business logicinternal/services/
Database queryinternal/repository/ + add method to interface in interfaces.go
New DB tableinternal/models/ + new migration in scripts/migration/sql/
New env config variableconfig/config.go + .env.example
New middlewareinternal/middleware/ + register in main.go initFiber()
Reusable utilitypkg/

lp-reward-store-api Differences

Same layered structure, but uses MongoDB instead of PostgreSQL (no GORM — uses the official MongoDB driver). No scripts/migration/ directory. Same pkg/ utilities pattern.

Key Takeaways