A backend service for collecting and managing experience data, built with Go and PostgreSQL.
- RESTful API for experience data CRUD operations
- PostgreSQL for data persistence
- Redis for caching and background jobs
- Clean architecture with repository, service, and handler layers
- Docker Compose for local development
- Language: Go 1.23
- Database: PostgreSQL 16
- Cache: Redis 7
- Driver: pgx/v5
- HTTP: Standard library
net/http
.
├── cmd/
│ ├── api/ # API server entrypoint
│ ├── worker/ # Background jobs (future)
│ └── migrate/ # Migration runner
├── internal/
│ ├── api/
│ │ ├── handlers/ # HTTP request handlers
│ │ └── middleware/ # HTTP middleware
│ ├── service/ # Business logic
│ ├── repository/ # Data access layer
│ └── models/ # Domain models
├── pkg/
│ └── database/ # Database utilities
├── migrations/ # SQL migrations
└── tests/ # Integration tests
- Go 1.23 or higher
- Docker and Docker Compose
- Make (optional, for convenience)
-
Clone the repository and navigate to the project directory
-
Set up the development environment:
make setupThis will:
- Start PostgreSQL and Redis containers
- Create a
.envfile from.env.example - Run database migrations
- Start the API server:
make runThe server will start on http://localhost:8080
If you prefer not to use Make:
- Start Docker containers:
docker-compose up -d- Copy environment variables:
cp .env.example .env- Run migrations:
go run ./cmd/migrate/main.go- Start the server:
go run ./cmd/api/main.goGET /health- Health check endpoint
POST /v1/experiences
Content-Type: application/json
{
"source_type": "survey",
"source_id": "survey-123",
"source_name": "Customer Feedback Survey",
"field_id": "question-1",
"field_label": "How satisfied are you?",
"field_type": "rating",
"value_number": 5,
"metadata": {"campaign": "summer-2025"},
"language": "en",
"user_identifier": "user-abc"
}GET /v1/experiences/{id}GET /v1/experiences?source_type=survey&limit=50&offset=0Query parameters:
source_type- Filter by source typesource_id- Filter by source IDfield_id- Filter by field IDuser_identifier- Filter by user identifierlimit- Number of results (default: 100, max: 1000)offset- Pagination offset
PATCH /v1/experiences/{id}
Content-Type: application/json
{
"value_number": 4,
"metadata": {"updated": true}
}DELETE /v1/experiences/{id}make help # Show all available commands
make build # Build all binaries
make run # Run the API server
make test # Run tests
make migrate # Run database migrations
make docker-up # Start Docker containers
make docker-down # Stop Docker containers
make clean # Clean build artifactsmake testMigrations are stored in the migrations/ directory and are executed in alphabetical order.
To run migrations:
make migrateOr manually:
go run ./cmd/migrate/main.goSee .env.example for all available configuration options:
DATABASE_URL- PostgreSQL connection stringREDIS_URL- Redis connection stringPORT- HTTP server port (default: 8080)ENV- Environment (development/production)
curl -X POST http://localhost:8080/v1/experiences \
-H "Content-Type: application/json" \
-d '{
"source_type": "form",
"field_id": "email",
"field_type": "text",
"value_text": "user@example.com"
}'curl http://localhost:8080/v1/experiencescurl -X PATCH http://localhost:8080/v1/experiences/{id} \
-H "Content-Type: application/json" \
-d '{
"metadata": {"verified": true}
}'curl -X DELETE http://localhost:8080/v1/experiences/{id}The application follows a clean architecture pattern:
- Handlers - Handle HTTP requests and responses
- Service - Contain business logic and validation
- Repository - Handle data access and queries
- Models - Define domain entities and DTOs
This separation allows for:
- Easy testing and mocking
- Clear separation of concerns
- Simple maintenance and refactoring