This project is a simple multi-tenant application built with Go (Golang) and PostgreSQL. It demonstrates how to handle multi-tenancy using domain-based tenant isolation, where each tenant's data is identified using a unique domain in the request.
- Multi-Tenancy: Isolates tenant data by the domain name provided in the HTTP request.
- PostgreSQL Integration: Uses PostgreSQL as the database for storing tenants and users.
- Database Migrations: Uses
golang-migrate
for database migrations to manage schema changes. - Middleware: Injects tenant data into the request context based on the domain in the request.
multi-tenant-go-app/
├── config/ # Database configuration and initialization
├── controllers/ # HTTP handlers and API logic
├── middleware/ # Tenant context middleware
├── models/ # Database models and queries
├── routes/ # API routing
├── memory-management-go/ # Memory management in go
├── migrations/ # Database migration files
├── reliable-software-go # Testing Tools
├── modular-code-go # Structuring Go Applications with Packages
├── error-handling-go # Error Handling
├── go-performance-optimization
├── secure-file-upload
├── .env # Environment variables (DB configuration)
├── .env.example # Tetsing Environment variables
├── go.mod # Go module file (dependencies)
├── go.sum # Go dependency versions
└── main.go # Application entry point
- Go (Golang): Installation Instructions
- PostgreSQL: Installation Instructions
- golang-migrate: CLI tool for database migrations.
-
Clone the repository:
git clone https://github.com/your-username/multi-tenant-go-app.git cd multi-tenant-go-app
-
Install Go dependencies:
go mod tidy
-
Set up PostgreSQL:
-
Install PostgreSQL on your system if you haven't already.
-
Create a database and user for the app:
CREATE DATABASE multi_tenant_app; CREATE USER tenant_user WITH PASSWORD 'tenant_password'; GRANT ALL PRIVILEGES ON DATABASE multi_tenant_app TO tenant_user;
-
-
Configure environment variables:
-
Create a
.env
file in the root of your project and configure your PostgreSQL credentials:DB_HOST=localhost DB_PORT=5432 DB_USER=tenant_user DB_PASSWORD=tenant_password DB_NAME=multi_tenant_app DATABASE_URL=postgres://tenant_user:tenant_password@localhost:5432/multi_tenant_app?sslmode=disable
-
-
Run Database Migrations:
-
Install
golang-migrate
CLI if you haven't yet:brew install golang-migrate # MacOS
For Linux, follow the instructions here.
-
Run migrations to set up the database schema:
migrate -path ./migrations -database $DATABASE_URL up
-
-
Run the Application:
go run main.go
If everything is configured correctly, you should see:
Database connected successfully. Migrations applied successfully.
-
Log in to PostgreSQL and insert a tenant into the
tenants
table:INSERT INTO tenants (name, domain) VALUES ('Tenant1', 'tenant1.localhost:8080');
-
Insert a user associated with the tenant:
INSERT INTO users (tenant_id, name, email, password_hash) VALUES (1, 'John Doe', 'john.doe@example.com', 'somehashedpassword');
You can test the API with tools like curl
or Postman. Ensure you use the Host
header to specify the tenant domain.
Use the following curl
command to retrieve the users for Tenant1
:
curl -H "Host: tenant1.localhost:8080" http://localhost:8080/users
You should see a response like:
[
{
"id": 1,
"name": "John Doe",
"email": "john.doe@example.com"
}
]
- GET /users: Returns all users for the current tenant based on the request's domain.
- Tenant not found: Ensure that the tenant exists in the
tenants
table, and the domain matches exactly (including port number). - Database connection issues: Double-check your
.env
configuration and verify that the PostgreSQL service is running. - Migrations failed: Ensure that the
migrations
folder contains both.up.sql
and.down.sql
files for each migration.
This multi-tenant Go app efficiently handles concurrent operations and background tasks using Go’s concurrency features.
When users are requested for a tenant, additional user-related data is fetched concurrently using goroutines. This improves performance by allowing multiple operations to execute in parallel, reducing the overall response time.
After the API response is sent, background jobs (like sending emails) are delegated to a worker pool. These tasks are processed asynchronously, without blocking the main request, ensuring scalability under heavy load.
The application implements a worker pool to manage background tasks efficiently. Each worker handles tasks such as sending emails for users in the background, logged in the console as they complete.
cd memory-management-go
This part demonstrates memory management techniques and pointer usage in Go. The program highlights the difference between passing variables by value vs. by pointer and showcases the use of new
and make
for memory allocation.
This project is licensed under the MIT License.