Getting Started with PostgreSQL ​
Get up and running with the goserve PostgreSQL example API server.
The project includes the following dependencies (automatically managed):
- goserve - Go backend framework
- Gin - HTTP web framework
- PostgreSQL Driver - pgx driver for PostgreSQL
- go-redis - Redis client
- JWT - JSON Web Tokens for authentication
- Validator - Request validation
- Viper - Configuration management
- Crypto - Cryptographic utilities
Prerequisites ​
Before you begin, ensure you have the following installed:
Required ​
- Go 1.21+ - Download
- Docker & Docker Compose - Install Guide
- Git - Download
Optional (for local development without Docker) ​
Verify Installation ​
# Check Go version
go version
# Should output: go version go1.21.x or higher
# Check Docker
docker --version
docker compose version
# Check Git
git --versionQuick Start ​
Fastest way to run and ping the API:
git clone https://github.com/afteracademy/goserve-example-api-server-postgres.git
cd goserve-example-api-server-postgres
go run .tools/rsa/keygen.go && go run .tools/copy/envs.go
docker compose up --build -d
curl http://localhost:8080/healthIf you need the details, continue below.
1. Clone the Repository ​
git clone https://github.com/afteracademy/goserve-example-api-server-postgres.git
cd goserve-example-api-server-postgres2. Generate RSA Keys ​
The application uses RSA keys for JWT token signing:
go run .tools/rsa/keygen.goThis creates keys/private.pem and keys/public.pem.
3. Create Environment Files ​
Copy example environment files:
go run .tools/copy/envs.goThis creates .env and .test.env from their example templates.
4. Start with Docker Compose ​
Launch all services (PostgreSQL, Redis, and the API server):
docker compose up --buildThe API will be available at: http://localhost:8080
5. Verify the Installation ​
Check the health of your API:
curl http://localhost:8080/healthYour First API Request ​
1. Get an API Key ​
Set an API key in your environment, then reuse it:
export API_KEY=your-api-keyNote: API_KEY 1D3F2DD1A5DE725DD4DF1D82BBB37 is created as default by this project through postgres seed sql scripts.
If your database is empty, create an entry in the api_keys table.
See API key setup for more details.
2. Sign Up ​
curl --location 'http://localhost:8080/auth/signup/basic' \
--header 'x-api-key: 1D3F2DD1A5DE725DD4DF1D82BBB37' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "ali@afteracademy.com",
"password": "123456",
"name": "Janishar Ali"
}'Response:
{
"code": "10000",
"status": 200,
"message": "success",
"data": {
"user": {
"id": "df7b4663-c595-4f0b-ba9d-6ac3d3dfe244",
"email": "ali@afteracademy.com",
"name": "Janishar Ali",
"roles": [
{
"id": "17c8077b-d5c2-42d8-a42b-9a0469c54209",
"code": "LEARNER"
}
]
},
"tokens": {
"accessToken": "...",
"refreshToken": "..."
}
}
}2. Sign In ​
curl --location 'http://localhost:8080/auth/signin/basic' \
--header 'x-api-key: 1D3F2DD1A5DE725DD4DF1D82BBB37' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "ali@afteracademy.com",
"password": "123456"
}'You must provide Roles to this user in the database to access protected routes. ​
You can use the default admin user seeded in the database:
curl --location 'http://localhost:8080/auth/signin/basic' \
--header 'x-api-key: 1D3F2DD1A5DE725DD4DF1D82BBB37' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "admin@afteracademy.com",
"password": "changeit"
}'Response
{
"code": "10000",
"status": 200,
"message": "success",
"data": {
"user": {
"_id": "df7b4663-c595-4f0b-ba9d-6ac3d3dfe244",
"email": "admin@afteracademy.com",
"name": "Admin",
"roles": [
{
"_id": "df7b4663-c595-4f0b-ba9d-6ac3d3dfe244",
"code": "LEARNER"
},
{
"_id": "df7b4663-c595-4f0b-ba9d-6ac3d3dfe244",
"code": "AUTHOR"
},
{
"_id": "df7b4663-c595-4f0b-ba9d-6ac3d3dfe244",
"code": "EDITOR"
},
{
"_id": "df7b4663-c595-4f0b-ba9d-6ac3d3dfe244",
"code": "ADMIN"
}
]
},
"tokens": {
"accessToken": "...",
"refreshToken": "..."
}
}
}Roles ​
You must assign appropriate roles to users in the database to access protected routes. You can do this by directly updating the users table in the PostgreSQL database. You will find the roles defined in api/user/model/role.go.
const RolesTableName = "roles"
type RoleCode string
const (
RoleCodeLearner RoleCode = "LEARNER"
RoleCodeAdmin RoleCode = "ADMIN"
RoleCodeAuthor RoleCode = "AUTHOR"
RoleCodeEditor RoleCode = "EDITOR"
)
type Role struct {
ID uuid.UUID
Code RoleCode
Status bool
CreatedAt time.Time
UpdatedAt time.Time
}Architecture Overview ​
This example demonstrates goserve's architecture with Postgres:
Key Components ​
- Postgres: Relational database for structured data storage
- Redis: High-performance caching layer
- JWT Authentication: RSA-signed tokens for secure authentication
- API Key Protection: Infrastructure-level security
- Feature-Based Structure: Organized by business domains
Directory Structure ​
goserve-example-api-server-postgres/
├── api/ # API feature modules
│ └── sample/ # Sample feature
│ ├── dto/ # Data Transfer Objects
│ ├── model/ # Postgres document models
│ ├── controller.go # HTTP handlers
│ └── service.go # Business logic
├── cmd/ # Application entry point
│ └── main.go # Main function
├── common/ # Shared utilities
├── config/ # Configuration
├── startup/ # Server initialization
│ ├── server.go # Server setup
│ ├── module.go # Dependency injection
│ └── indexes.go # Database indexes
├── tests/ # Integration tests
├── .tools/ # Code generation tools
└── keys/ # RSA keys for JWTDevelopment Workflow ​
Fast checks (recommended) ​
- Tests:
docker exec -t goserver-postgres go test -v ./... - Health:
curl http://localhost:8080/health - Seed reminder: ensure at least one API key exists before hitting protected routes.
Running Tests ​
# Run all tests
docker exec -t goserver-postgres go test -v ./...
# Run specific test
docker exec -t goserver-postgres go test -v ./tests/Code Generation ​
Generate new API features:
go run .tools/apigen.go your-feature-nameThis creates the complete directory structure and skeleton files for a new feature.
Local Development ​
For local development without Docker:
- Install dependencies:bash
go mod tidy - Start Postgres and Redis locally (or via Docker).
- Update
.envand.test.env:DB_HOST=localhost REDIS_HOST=localhost - Run the application:bash
go run cmd/main.go
If ports are already in use:
# Check what's using the ports
lsof -i :8080
lsof -i :27017
lsof -i :6379
# Update .env file with different ports
SERVER_PORT=8081
DB_PORT=27018
REDIS_PORT=6380Postgres Connection Issues ​
# Check Postgres status
docker ps | grep postgres
# Connect to Postgres
docker exec -it <postgres_container> postgres
# Verify connection
go run cmd/main.goPermission Issues ​
# Fix file permissions
chmod +x .tools/rsa/keygen.go
chmod +x .tools/copy/envs.goObservability ​
- Health endpoint:
GET /healthon port 8080 - Logs:
docker compose logs -f apior the local process output
