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-migratefor 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
.envfile 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-migrateCLI if you haven't yet:brew install golang-migrate # MacOSFor 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
tenantstable: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/usersYou 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
tenantstable, and the domain matches exactly (including port number). - Database connection issues: Double-check your
.envconfiguration and verify that the PostgreSQL service is running. - Migrations failed: Ensure that the
migrationsfolder contains both.up.sqland.down.sqlfiles 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.