A SaaS web application backend built with Go and Gin, featuring Vue.js frontend, Heroku Postgres Advanced with follower pools, Redis for background jobs, and JWT authentication.
- RESTful API with CRUD operations for customers and accounts
- JWT Authentication for secure API access
- Background Jobs using Asynq for data aggregation
- Analytics Endpoints that read from follower pools
- Health Checks and Prometheus metrics
- Vue.js Frontend with Bootstrap styling
- Swagger/OpenAPI Documentation with interactive API testing
π Architecture Documentation: See ARCHITECTURE.md for detailed architecture diagrams, leader/follower pattern implementation, and system design decisions.
- Backend: Go + Gin
- Frontend: Vue.js 3 + Bootstrap 5
- Database: PostgreSQL (Heroku Postgres Advanced)
- Cache/Jobs: Redis + Asynq
- Monitoring: Prometheus
saas-go-app/
βββ cmd/
β βββ server/
β βββ main.go # Application entry point
βββ internal/
β βββ api/ # API handlers
β βββ auth/ # JWT authentication
β βββ db/ # Database connection and migrations
β βββ jobs/ # Background job handlers
β βββ models/ # Data models
βββ web/
β βββ frontend/ # Vue.js frontend application
βββ Makefile # Common tasks
βββ go.mod # Go dependencies
βββ README.md
- Go 1.21+
- Node.js 18+
- PostgreSQL (or Heroku Postgres)
- Redis (optional, for background jobs)
- Install dependencies:
make deps- Create a
.envfile (seeenv.example):
# For local development, set up PostgreSQL and Redis locally
# Or use Docker:
# docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres
# docker run -d -p 6379:6379 redis
DATABASE_URL=postgres://user:password@localhost:5432/saas_go_app?sslmode=disable
ANALYTICS_DB_URL=postgres://user:password@localhost:5432/saas_go_app?sslmode=disable # Can use same DB for local dev
REDIS_URL=redis://localhost:6379/0
JWT_SECRET=your-secret-key-change-in-production
PORT=8080
SEED_DATA=true # Set to "true" to populate database with sample data on startupNote: On Heroku:
DATABASE_URLandPORTare automatically set by HerokuANALYTICS_DB_URLmust be set manually to your follower pool connection string (see HEROKU_SETUP.md)REDIS_URLis automatically set if you provision Heroku Redis addonJWT_SECRETmust be set manually:heroku config:set JWT_SECRET=your-secret-key
- Run the server:
make run
# or
go run ./cmd/serverThe server will automatically create database tables on startup.
Default Test User (created when seeding data):
- Username:
admin - Password:
admin123
Note: The default user is only created when
SEED_DATA=trueand the users table is empty. For production, you should register your own user and change/remove the default credentials.
Performance Demo Data (for NGPG showcase): To generate large datasets for demonstrating NGPG performance features, set:
SEED_DATA=true
SEED_PERFORMANCE_DATA=true
SEED_CUSTOMERS=1000 # Number of customers (default: 1000)
SEED_ACCOUNTS_PER_CUSTOMER=5 # Accounts per customer (default: 5)This will generate thousands of records to showcase:
- Read scaling with follower pools
- Analytics query performance
- Automatic query routing between leader and followers
The performance data generation creates realistic company names, emails, and account distributions with varied statuses.
Clear and Reseed Database (for local development):
# Basic reseed
make reseed
# Reseed with performance data
SEED_PERFORMANCE_DATA=true make reseed
# Custom amount
SEED_PERFORMANCE_DATA=true SEED_CUSTOMERS=2000 SEED_ACCOUNTS_PER_CUSTOMER=10 make reseedThis will clear all existing customers and accounts, then regenerate data based on your environment variables.
- Navigate to the frontend directory:
cd web/frontend- Install dependencies:
npm install- Start the development server:
npm run devThe frontend will be available at http://localhost:3000 and will proxy API requests to http://localhost:8080.
For Production/Heroku Deployment:
- Build the frontend:
cd web/frontend
npm install
npm run build- The built files will be in
web/frontend/dist/ - The Go server will automatically serve these files when deployed
- See FRONTEND_DEPLOYMENT.md for detailed deployment options
π Interactive API Documentation: Access the full Swagger UI at
/swagger/index.htmlfor interactive testing, request/response schemas, and detailed endpoint documentation.
POST /api/auth/login- Login and get JWT tokenPOST /api/auth/register- Register a new user
GET /api/customers- Get all customersGET /api/customers/:id- Get customer by IDPOST /api/customers- Create a new customerPUT /api/customers/:id- Update customerDELETE /api/customers/:id- Delete customer
GET /api/accounts- Get all accountsGET /api/accounts/:id- Get account by IDPOST /api/accounts- Create a new accountPUT /api/accounts/:id- Update accountDELETE /api/accounts/:id- Delete account
GET /api/analytics- Get overall analyticsGET /api/analytics/customers/:customer_id- Get customer-specific analytics
GET /health- Health check endpointGET /metrics- Prometheus metrics
The API includes comprehensive interactive Swagger/OpenAPI documentation powered by Swagger UI. This provides a complete reference for all endpoints with the ability to test them directly from your browser.
Once the server is running, visit:
- Local Development:
http://localhost:8080/swagger/index.html - Heroku Production:
https://your-app-name.herokuapp.com/swagger/index.html
The Swagger UI provides:
- Complete API Documentation: All endpoints with descriptions, parameters, and examples
- Request/Response Schemas: Detailed JSON schemas for all request and response bodies
- Interactive Testing: Try any endpoint directly from the browser without external tools
- JWT Authentication: Built-in support for testing protected endpoints with Bearer tokens
- Model Definitions: View all data models (Customer, Account, etc.) with their fields and types
If you modify API handlers or add new endpoints, regenerate the Swagger documentation:
make swagger
# or manually:
swag init -g main.go -o ./docsThe Makefile will automatically use swag if installed, or fall back to go run if not.
- In Swagger UI, find the Authentication section (
/api/auth/login) - Click "Try it out"
- Enter your credentials:
{ "username": "your-username", "password": "your-password" } - Click "Execute" and copy the
tokenfrom the response
- Click the "Authorize" button at the top of the Swagger UI (π icon)
- In the "Value" field, enter:
Bearer {your-token}- Important: Include the word "Bearer" followed by a space, then your token
- Example:
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
- Click "Authorize" then "Close"
- Navigate to any protected endpoint (customers, accounts, analytics)
- Click on the endpoint to expand it
- Click "Try it out"
- Fill in any required parameters
- Click "Execute"
- View the response with status code, headers, and body
Note: Once authorized, all protected endpoints will automatically include your JWT token in the Authorization header.
π For detailed Heroku deployment instructions, see HEROKU_SETUP.md
# Login to Heroku
heroku login
# Create Heroku app
heroku create saas-go-app
# Provision Postgres Advanced
heroku addons:create heroku-postgresql:standard-0 --name saas-go-db
# (Optional) Provision Redis
heroku addons:create heroku-redis:hobby-dev
# Get DATABASE_URL
heroku config:get DATABASE_URL
# Set up follower pool for analytics (via Heroku Dashboard)
# Go to: https://dashboard.heroku.com/apps/saas-go-app
# Click on the database addon β Create Follower/Follower Pool
# Or check HEROKU_SETUP.md for detailed instructions
# Get ANALYTICS_DB_URL from follower
heroku config:get ANALYTICS_DB_URL
# Set environment variables
heroku config:set JWT_SECRET=your-production-secret-key
# Deploy
git push heroku main
# Open app
heroku openNote: The Procfile tells Heroku how to run your app. Heroku's Go buildpack will automatically detect go.mod and build your application. The binary name matches your module name (saas-go-app).
Automatically Set by Heroku:
DATABASE_URL- Automatically set byheroku-postgresqladdon (primary database)ANALYTICS_DB_URL- Automatically set when you create a follower pool (via Heroku Dashboard)REDIS_URL- Automatically set byheroku-redisaddon (if provisioned)PORT- Automatically set by Heroku platform
Manually Configured:
JWT_SECRET- You must set this manually:heroku config:set JWT_SECRET=your-secret-key
Important: When you provision Heroku Postgres Advanced and create a follower pool, Heroku automatically provides the connection URLs. You don't need to manually configure DATABASE_URL or ANALYTICS_DB_URL - they're set automatically by the addons.
The application is designed to work with or without these optional features:
-
Follower Pool (
ANALYTICS_DB_URL):- Optional - The app gracefully falls back to using the primary database for analytics queries if not configured
- Benefit: Offloads read-only analytics queries to a follower, reducing load on the primary database
- Requirement: Requires Heroku Postgres Advanced (requires NGPG pilot program access)
- Status: App works perfectly without it - analytics endpoints will use the primary DB
-
Redis (
REDIS_URL):- Optional - Background job processing is disabled if not configured
- Benefit: Enables async background jobs for data aggregation
- Status: App runs fine without it - you'll see a log message that background jobs are disabled
Summary: The only truly required components are:
- PostgreSQL database (
DATABASE_URL) - JWT secret (
JWT_SECRET)
Everything else is optional and the app will work without them, just with reduced functionality.
make test
# or with coverage
make test-coveragemake buildmake fmtBackground jobs are processed using Asynq. Jobs are enqueued for data aggregation tasks. The job processor runs automatically when REDIS_URL is configured.
Example: Enqueue an aggregation task (can be added to API handlers):
import "saas-go-app/internal/jobs"
client, _ := jobs.NewClient(os.Getenv("REDIS_URL"))
jobs.EnqueueAggregationTask(client, time.Now())MIT