@sysnee/pgs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,314 @@
1
+ # PostgreSQL Multi-Tenant Instance Manager
2
+
3
+ Dynamic PostgreSQL multi-tenant management system providing complete database isolation by creating dedicated PostgreSQL instances per tenant, with intelligent routing via HAProxy.
4
+
5
+ > 📖 **For detailed project definition, architecture, and comparison with similar solutions, see [PROJECT.md](./PROJECT.md)**
6
+
7
+ ## Usage
8
+
9
+ ### Create a new tenant instance
10
+
11
+ ```bash
12
+ npm run create <tenant-id> [--password <password>]
13
+ ```
14
+
15
+ Example:
16
+ ```bash
17
+ npm run create tenant1
18
+ npm run create tenant2 --password mycustompass
19
+ ```
20
+
21
+ New tenants are created with external access **disabled** by default.
22
+
23
+ ### List all tenants
24
+
25
+ ```bash
26
+ npm run list
27
+ ```
28
+
29
+ Shows all tenants with their external access status.
30
+
31
+ ### Remove a tenant
32
+
33
+ ```bash
34
+ npm run remove <tenant-id>
35
+ ```
36
+
37
+ ### Start services
38
+
39
+ ```bash
40
+ npm run start # Start all services (including HAProxy)
41
+ npm run start -- --tenant tenant1 # Start specific tenant
42
+ ```
43
+
44
+ ### Stop services
45
+
46
+ ```bash
47
+ npm run stop # Stop all services
48
+ npm run stop -- --tenant tenant1 # Stop specific tenant
49
+ ```
50
+
51
+ ## How it works
52
+
53
+ - HAProxy listens on port 5432 and routes connections based on the PostgreSQL username
54
+ - Each tenant connects using their tenant ID as the username (e.g., `tecnolab`)
55
+ - External access is controlled via `tenant-access.json`
56
+ - Tenants are isolated in their own PostgreSQL containers on a Docker bridge network
57
+ - Only HAProxy has external port mapping; PostgreSQL containers are internal only
58
+
59
+ ## Connection
60
+
61
+ After creating a tenant and enabling external access:
62
+
63
+ ```bash
64
+ psql -h localhost -p 5432 -U <tenant-id> -d <tenant-id>
65
+ ```
66
+
67
+ ## Project Definition
68
+
69
+ ### What It Is
70
+
71
+ A **dynamic PostgreSQL multi-tenant management system** that provides complete database isolation by creating dedicated PostgreSQL instances per tenant. The system uses HAProxy with custom PostgreSQL protocol parsing to route connections intelligently while maintaining complete tenant isolation at the database server level.
72
+
73
+ ### Core Concept
74
+
75
+ Instead of sharing a single PostgreSQL instance with multiple databases (shared database architecture), this system creates **one PostgreSQL container per tenant**, ensuring:
76
+
77
+ - **Complete Data Isolation**: Each tenant has its own PostgreSQL process and data directory
78
+ - **Independent Scaling**: Resources can be allocated per tenant
79
+ - **Enhanced Security**: No risk of cross-tenant data access
80
+ - **Simplified Operations**: Each tenant can be managed independently
81
+
82
+ ### Key Features
83
+
84
+ 1. **Dynamic Tenant Provisioning**
85
+ - Create new PostgreSQL instances on-demand
86
+ - Automatic volume and network configuration
87
+ - Custom initialization scripts per tenant
88
+
89
+ 2. **Intelligent Routing**
90
+ - HAProxy parses PostgreSQL protocol to extract username
91
+ - Routes connections to correct tenant backend automatically
92
+ - Single external port (5432) for all tenants
93
+
94
+ 3. **Access Control**
95
+ - Per-tenant external access enable/disable
96
+ - Secure by default (access disabled on creation)
97
+ - Runtime access control without service restart
98
+
99
+ 4. **Complete Isolation**
100
+ - Separate Docker containers per tenant
101
+ - Isolated volumes for data persistence
102
+ - Network isolation via Docker bridge network
103
+ - No shared processes or memory
104
+
105
+ 5. **Zero-Downtime Operations**
106
+ - Graceful HAProxy reloads
107
+ - Independent tenant management
108
+ - No impact on other tenants during operations
109
+
110
+ ## Architecture
111
+
112
+ ```
113
+ ┌─────────────────────────────────────────────────────────┐
114
+ │ External Access │
115
+ │ (localhost:5432) │
116
+ └──────────────────────┬──────────────────────────────────┘
117
+
118
+
119
+ ┌─────────────────────────────────────────────────────────┐
120
+ │ HAProxy Proxy │
121
+ │ ┌──────────────────────────────────────────────────┐ │
122
+ │ │ Frontend: postgres_frontend │ │
123
+ │ │ - Listens on port 5432 │ │
124
+ │ │ - Parses PostgreSQL protocol (Lua script) │ │
125
+ │ │ - Extracts username from startup packet │ │
126
+ │ │ - Checks tenant-access.json for permissions │ │
127
+ │ └──────────────────────────────────────────────────┘ │
128
+ └──────────────────────┬──────────────────────────────────┘
129
+
130
+ ┌──────────────┼──────────────┐
131
+ │ │ │
132
+ ▼ ▼ ▼
133
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
134
+ │ Backend │ │ Backend │ │ Backend │
135
+ │ pgs_tenant1 │ │ pgs_tenant2 │ │ pgs_tenant3 │
136
+ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
137
+ │ │ │
138
+ ▼ ▼ ▼
139
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
140
+ │ PostgreSQL │ │ PostgreSQL │ │ PostgreSQL │
141
+ │ Container 1 │ │ Container 2 │ │ Container 3 │
142
+ │ │ │ │ │ │
143
+ │ Port: 5432 │ │ Port: 5432 │ │ Port: 5432 │
144
+ │ (internal) │ │ (internal) │ │ (internal) │
145
+ │ │ │ │ │ │
146
+ │ Volume: │ │ Volume: │ │ Volume: │
147
+ │ pgdata_1 │ │ pgdata_2 │ │ pgdata_3 │
148
+ └──────────────┘ └──────────────┘ └──────────────┘
149
+ ```
150
+
151
+ ## Technical Implementation
152
+
153
+ ### Components
154
+
155
+ 1. **Manager Script (manager.js)**
156
+ - Node.js CLI tool for tenant lifecycle management
157
+ - Dynamically generates docker-compose.yml entries
158
+ - Manages HAProxy configuration
159
+ - Controls tenant access permissions
160
+
161
+ 2. **HAProxy Reverse Proxy**
162
+ - TCP-level load balancer and router
163
+ - Custom Lua script for PostgreSQL protocol parsing
164
+ - Routes based on extracted username
165
+ - Per-tenant access control
166
+
167
+ 3. **PostgreSQL Protocol Parser (pg-route.lua)**
168
+ - Parses binary PostgreSQL startup packet
169
+ - Extracts username and connection parameters
170
+ - Handles SSL negotiation
171
+ - Enforces access control policies
172
+
173
+ 4. **Docker Infrastructure**
174
+ - Separate container per tenant
175
+ - Bridge network for internal communication
176
+ - Persistent volumes for data
177
+ - Isolated execution environments
178
+
179
+ ### Connection Flow
180
+
181
+ 1. Client connects to `localhost:5432` with username `tenant_id`
182
+ 2. HAProxy receives connection and invokes Lua script
183
+ 3. Script parses PostgreSQL startup packet and extracts username
184
+ 4. Script checks `tenant-access.json` for permission
185
+ 5. If allowed, routes to backend `pgs_{tenant_id}`
186
+ 6. Backend forwards to PostgreSQL container on internal network
187
+ 7. Connection established with complete isolation
188
+
189
+ ## Comparison with Similar Solutions
190
+
191
+ ### Shared Database Architecture
192
+
193
+ **Traditional Multi-Tenant PostgreSQL:**
194
+ - Single PostgreSQL instance
195
+ - Multiple databases/schemas per instance
196
+ - Shared processes and memory
197
+ - Risk of cross-tenant data access
198
+ - Less isolation
199
+
200
+ **This Solution:**
201
+ - Multiple PostgreSQL instances
202
+ - One instance per tenant
203
+ - Complete process isolation
204
+ - Zero risk of cross-tenant access
205
+ - Maximum isolation
206
+
207
+ ### Similar Open Source Solutions
208
+
209
+ #### 1. **PgBouncer**
210
+ - **Purpose**: Connection pooling, not tenant isolation
211
+ - **Difference**: Pools connections to single instance; this creates separate instances
212
+ - **Use Case**: Different - PgBouncer optimizes connections; this isolates tenants
213
+
214
+ #### 2. **Citus**
215
+ - **Purpose**: PostgreSQL extension for distributed PostgreSQL
216
+ - **Difference**: Shards data across nodes; this creates separate instances per tenant
217
+ - **Use Case**: Horizontal scaling vs. tenant isolation
218
+
219
+ #### 3. **Patroni + HAProxy**
220
+ - **Purpose**: High availability and load balancing
221
+ - **Difference**: Replicates single database; this creates isolated instances
222
+ - **Use Case**: HA for single database vs. multi-tenant isolation
223
+
224
+ #### 4. **Schema-based Multi-tenancy**
225
+ - **Purpose**: Share database, separate schemas
226
+ - **Difference**: Shared instance; this uses separate instances
227
+ - **Use Case**: Resource efficiency vs. complete isolation
228
+
229
+ #### 5. **Row-level Security (RLS)**
230
+ - **Purpose**: Application-level tenant isolation
231
+ - **Difference**: Logic-based separation; this uses infrastructure isolation
232
+ - **Use Case**: Application isolation vs. infrastructure isolation
233
+
234
+ ### Unique Aspects of This Solution
235
+
236
+ 1. **Instance-per-tenant at infrastructure level**
237
+ - Not just database or schema separation
238
+ - Complete process and memory isolation
239
+
240
+ 2. **Dynamic provisioning with single external port**
241
+ - No need for port management
242
+ - Automatic routing based on connection parameters
243
+
244
+ 3. **Protocol-aware routing**
245
+ - Parses PostgreSQL binary protocol
246
+ - Routes before connection completion
247
+ - Handles SSL negotiation
248
+
249
+ 4. **Runtime access control**
250
+ - Enable/disable tenant access without restart
251
+ - No downtime for access changes
252
+
253
+ 5. **Docker-native architecture**
254
+ - Leverages container isolation
255
+ - Simple deployment and scaling
256
+ - Resource limits per tenant
257
+
258
+ ## Use Cases
259
+
260
+ ### Ideal For
261
+
262
+ - **SaaS Applications** requiring strict tenant data isolation
263
+ - **Healthcare/Finance** applications with compliance requirements
264
+ - **Multi-tenant platforms** needing independent scaling
265
+ - **Development/Testing** environments with isolated databases
266
+ - **Legacy application migration** requiring tenant separation
267
+
268
+ ### Not Ideal For
269
+
270
+ - Thousands of tenants (resource overhead)
271
+ - Shared resource requirements
272
+ - Simple multi-tenant applications without strict isolation needs
273
+ - Environments requiring minimal resource usage
274
+
275
+ ## Advantages
276
+
277
+ ✅ **Maximum Isolation**: Complete process and data separation
278
+ ✅ **Security**: Zero risk of cross-tenant data access
279
+ ✅ **Flexibility**: Independent scaling and management per tenant
280
+ ✅ **Simplicity**: Single external port, automatic routing
281
+ ✅ **Compliance**: Easier to meet regulatory requirements
282
+ ✅ **Debugging**: Isolated environments simplify troubleshooting
283
+
284
+ ## Trade-offs
285
+
286
+ ⚠️ **Resource Usage**: Higher memory/CPU per tenant
287
+ ⚠️ **Management Overhead**: More containers to manage
288
+ ⚠️ **Scaling Limits**: Practical limit on number of tenants per host
289
+ ⚠️ **Backup Complexity**: Need to backup multiple instances
290
+
291
+ ## Technology Stack
292
+
293
+ - **Runtime**: Node.js (ES Modules)
294
+ - **Container Orchestration**: Docker Compose
295
+ - **Reverse Proxy**: HAProxy with Lua scripting
296
+ - **Database**: PostgreSQL 18+
297
+ - **Protocol Parsing**: Custom Lua script
298
+ - **Configuration**: YAML (docker-compose.yml), JSON (tenant-access.json)
299
+
300
+ ## Future Enhancements
301
+
302
+ - [ ] Health checks and automatic failover
303
+ - [ ] Backup/restore automation per tenant
304
+ - [ ] Resource limits (CPU/memory) per tenant
305
+ - [ ] Monitoring and metrics collection
306
+ - [ ] Tenant migration tools
307
+ - [ ] Kubernetes support
308
+ - [ ] Connection pooling per tenant
309
+ - [ ] SSL/TLS termination
310
+
311
+ ## License & Status
312
+
313
+ This is a custom solution built for specific multi-tenant requirements. It combines open-source tools (HAProxy, PostgreSQL, Docker) with custom routing logic to achieve instance-per-tenant isolation with intelligent connection routing.
314
+
@@ -0,0 +1,16 @@
1
+ services:
2
+ haproxy:
3
+ image: haproxy:latest
4
+ container_name: postgres_proxy
5
+ ports:
6
+ - '5432:5432'
7
+ volumes:
8
+ - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
9
+ - ./haproxy-lua:/etc/haproxy/lua:ro
10
+ - ./tenant-access.json:/etc/haproxy/tenant-access.json:ro
11
+ networks:
12
+ - postgres_network
13
+ restart: unless-stopped
14
+ networks:
15
+ postgres_network:
16
+ driver: bridge