A web-based PostgreSQL and Redis management tool for querying multiple database instances across cloud providers simultaneously β with role-based access, full audit trails, and release verification built in.
Quick Start Β· Features Β· Architecture Β· API Β· Deploy Β· Config Guide
Managing PostgreSQL across AWS, GCP, or any cloud means juggling connections, credentials, and comparing results manually. This tool gives you one UI to query them all β run the same SQL on every cloud at once, compare results sideβbyβside, and maintain a full audit trail with roleβbased access control.
| Run the same query on AWS and GCP simultaneously. Catch divergence after migrations. | One query, every instance, sideβbyβside results with timing per cloud. | Execute DDL across environments in one shot, with rollback on failure. | Complete execution log with roleβbased permissions and passwordβprotected destructive ops. |
ββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Multiβcloud execution β Query all clouds simultaneously or target a specific one β
β Dynamic configuration β Add clouds and databases via JSON β zero code changes β
β Async query engine β Nonβblocking execution with progress + cancellation β
β Multiβstatement support β Batches separated by ';' with perβstatement results β
β Roleβbased access β MASTER / USER / READER with granular SQL control β
β Passwordβprotected ops β DROP, TRUNCATE, DELETE, ALTER require MASTER password β
β Query history & audit β Full execution log with filtering and pagination β
β Env variable substitution β ${VAR_NAME} in config for secure credential management β
ββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Monaco Editor | VS Code's editor engine with PostgreSQL syntax highlighting |
| SQL formatting | Oneβclick format, PostgreSQL dialect, uppercase keywords |
| Autoβsave | Drafts saved every 5 seconds to localStorage with restore on reload |
| Keyboard shortcuts | β/Ctrl + Enter to execute |
| Dark theme | Full dark mode UI |
| Sideβbyβside cloud results | Colorβcoded expandable sections per cloud |
| Table and JSON views | Toggle between formatted table and raw JSON |
| CSV / JSON export | Download results per cloud |
| Perβstatement breakdown | Individual results for each statement in a batch |
| Execution timing | Duration in milliseconds per cloud |
| Multiβcloud Redis | Execute commands across all configured Redis instances simultaneously |
| 50+ commands | String, Hash, List, Set, Sorted Set, Stream, Geo, and utility commands |
| Pattern SCAN | Find keys matching patterns with preview, pagination, and bulk delete |
| Command validation | Syntax checking and dangerous command blocking |
| Write history | Full audit trail of all Redis write operations |
| Git diff analysis | Extract SQL migration files between any two commits, tags, or branches |
| Autoβverification | Verify each DDL against readβonly replicas (CREATE/ALTER TABLE, indexes, constraints, NOT NULL, DEFAULT, TYPE) |
| Multiβdatabase support | Separate verification per database (BPP, BAP, dashboards, etc.) |
| Smart categorization | Group into ALTER (schema), ALTER NOT NULL, INSERT, UPDATE sections |
| Copy at every level | Copy pending SQL per database, folder, file, or category |
| Run on DB Manager | Send selected queries directly to the DB Manager for execution |
| Export checklist | Generate Markdown or Slackβformatted release checklists |
| Readβonly safety | Triple protection: read replica host + readβonly user + poolβlevel default_transaction_read_only=on |
| Auto repo sync | Init container clones repo; git fetch on page load with 5βmin cooldown |
| User registration | Selfβservice signup, requires MASTER activation |
| Activate / deactivate | Enable or disable user accounts |
| Role assignment | Promote or demote between MASTER / USER / READER |
| User search | Search by username, name, or email |
| User deletion | Remove accounts (cannot delete MASTER users) |
| Operation | MASTER | USER | READER |
|---|---|---|---|
| SELECT | β | β | β |
| INSERT / UPDATE | β | β | β |
| CREATE TABLE / INDEX | β | β | β |
| ALTER TABLE (ADD) | β | β | β |
| DELETE | β password | β | β |
| DROP / TRUNCATE | β password | β | β |
| ALTER DROP | β password | β | β |
| GRANT / REVOKE | β password | β | β |
| Redis READ commands | β | β | β |
| Redis WRITE commands | β | β | β |
| Redis SCAN / KEYS | β | β | β |
| User management | β | β | β |
| Cancel any user's query | β | β | β |
β Blocked for all roles (including MASTER) SQL β
DROP/CREATE DATABASE,DROP/CREATE SCHEMA,ALTER/CREATE/DROP ROLE,ALTER/CREATE/DROP USERRedis βFLUSHDB,FLUSHALL,KEYS,EVAL,EVALSHA,SCRIPT DEBUG,CLIENT KILL,SHUTDOWN,BGSAVE,BGREWRITEAOF,CONFIG RESETSTAT,LASTSAVE
βββββββββββββββββββββββββββββββββββ
β Frontend β React 18 Β· TypeScript Β· MaterialβUI
β Nginx Β· :80 β Monaco Editor Β· Zustand
ββββββββββββββββββ¬βββββββββββββββββ
β REST
βΌ
βββββββββββββββββββββββββββββββββββ
β Backend β Express Β· TypeScript
β Node Β· :3000 β Winston logging Β· Zod validation
βββββ¬ββββββββββββββββββ¬ββββββββββββ
β β
βΌ βΌ
ββββββββββββ βββββββββββββββββββββββββββββββββββ
β Redis β β PostgreSQL Instances β
β β β Cloud 1 ββ DB1, DB2, ... β
β β β Cloud 2 ββ DB1, DB2, ... β
β β β Cloud N ββ ... β
ββββββββββββ βββββββββββββββββββββββββββββββββββ
| Layer | Technology |
|---|---|
| Frontend | React 18 Β· TypeScript Β· MaterialβUI Β· Monaco Editor Β· Zustand Β· Axios Β· Vite |
| Backend | Node.js Β· Express Β· TypeScript Β· nodeβpostgres Β· Zod Β· Winston Β· Helmet |
| Data | PostgreSQL 12+ Β· Redis 6+ (sessions + execution state) |
| Deployment | Docker (multiβstage) Β· Kubernetes Β· Nginx |
- Redis stores user sessions (shared across backend replicas) and async query execution state
- Backend is stateless β horizontally scalable behind a load balancer
- Frontend is an Nginxβserved SPA with runtime backend URL injection (no rebuild per environment)
- Connection pooling β 2β20 connections per database, 30s idle timeout, 10s connect timeout
- Sessions β HTTPβonly secure cookies, Redisβbacked
Node.js β₯ 18
PostgreSQL β₯ 12 (at least one instance to manage)
Redis β₯ 6
git clone https://github.com/vijaygupta18/Multi-Cloud-DB-Manager.git
cd Multi-Cloud-DB-Manager
cd backend && npm install
cd ../frontend && npm installCreate backend/config/databases.json:
| Key | Purpose |
|---|---|
primary |
Your main cloud. Must have exactly one entry. |
secondary |
Additional clouds. Add as many as you need, or leave as []. |
history |
Database where users and query audit trail are stored (can reuse an existing database). |
readReplicas optional |
Readβonly replica endpoints for Migration Verifier. |
migrations optional |
Git repo path and folderβtoβdatabase mapping for migration analysis. |
π‘ Use
${ENV_VAR}syntax for secrets β values are substituted from.envat startup.
Create backend/config/redis.json:
{
"primary": {
"cloudName": "aws",
"host": "redis.cluster.amazonaws.com",
"port": 6379,
"password": "${REDIS_PASSWORD}"
},
"secondary": [
{
"cloudName": "gcp",
"host": "redis.googleapis.com",
"port": 6379,
"password": "${GCP_REDIS_PASSWORD}"
}
]
}See
backend/CONFIG.mdfor the full configuration reference.
backend/.env
PORT=3000
NODE_ENV=development
REDIS_HOST=localhost
REDIS_PORT=6379
SESSION_SECRET=change-this-to-a-long-random-string
FRONTEND_URL=http://localhost:5173
RUN_MIGRATIONS=true
# Database credential variables referenced in databases.json
CLOUD2_DB_PASSWORD=your-secure-passwordfrontend/.env
VITE_API_URL=http://localhost:3000# Terminal 1 Β· Redis
redis-server
# Terminal 2 Β· Backend
cd backend && npm run dev
# Terminal 3 Β· Frontend
cd frontend && npm run devOpen β http://localhost:5173
-
Register a new account via the login page
-
Promote yourself to MASTER:
UPDATE dual_db_manager.users SET role = 'MASTER', is_active = true WHERE username = 'your-username';
-
Log out and log back in. You now have full access.
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Backend server port |
NODE_ENV |
development |
development or production |
REDIS_HOST |
localhost |
Redis hostname |
REDIS_PORT |
6379 |
Redis port |
REDIS_PASSWORD |
β | Redis password (optional) |
REDIS_DB |
0 |
Redis database number |
SESSION_SECRET |
β | Required. Random string for session encryption |
FRONTEND_URL |
http://localhost:5173 |
CORS allowed origin |
MAX_QUERY_TIMEOUT_MS |
300000 |
Overall query timeout (5 min) |
STATEMENT_TIMEOUT_MS |
300000 |
Perβstatement PostgreSQL timeout (5 min) |
REDIS_EXECUTION_TTL_SECONDS |
300 |
Async execution state TTL in Redis (5 min) |
RUN_MIGRATIONS |
false |
Autoβcreate dual_db_manager schema on startup |
Migrations autoβcreate (when RUN_MIGRATIONS=true) or run manually with npm run migrate.
dual_db_manager.users
| Column | Type | Description |
|---|---|---|
id |
UUID |
Primary key |
username |
VARCHAR(255) |
Unique login name |
password_hash |
TEXT |
bcrypt hash |
email |
VARCHAR(255) |
Unique email |
name |
VARCHAR(255) |
Display name |
role |
VARCHAR(50) |
MASTER, USER, or READER |
is_active |
BOOLEAN |
Account enabled (default: false) |
created_at |
TIMESTAMP |
Registration time |
dual_db_manager.query_history
| Column | Type | Description |
|---|---|---|
id |
UUID |
Primary key |
user_id |
UUID |
Foreign key to users |
query |
TEXT |
Executed SQL |
database_name |
VARCHAR(50) |
Target database |
execution_mode |
VARCHAR(50) |
both or specific cloud name |
cloud_results |
JSONB |
Perβcloud results with success, duration, rows |
created_at |
TIMESTAMP |
Execution time |
Both services use multiβstage builds for minimal image size.
# Build (use --platform linux/amd64 when deploying to x86 servers from ARM machines)
docker build --platform linux/amd64 -t multi-cloud-db-backend ./backend
docker build --platform linux/amd64 -t multi-cloud-db-frontend ./frontend
# Run backend
docker run -p 3000:3000 \
--env-file backend/.env \
multi-cloud-db-backend
# Run frontend (BACKEND_URL injected at runtime β no rebuild per environment)
docker run -p 80:80 \
-e BACKEND_URL=http://your-backend:3000 \
multi-cloud-db-frontendβ Health checks built in β Backend
GET /healthΒ· FrontendGET /
Manifests in k8s/:
| File | Description |
|---|---|
backend.yaml |
Backend Deployment (2 replicas) + Service + liveness/readiness probes |
frontend.yaml |
Frontend Deployment (2 replicas) + Nginx ConfigMap + Service |
secrets.yaml.example |
Template for secrets (copy to secrets.yaml and fill in) |
cp k8s/secrets.yaml.example k8s/secrets.yaml
# Edit secrets.yaml with base64-encoded values
kubectl apply -f k8s/Deployment defaults
- Rolling updates β 25% maxSurge, 25% maxUnavailable
- Backend β 200m CPU / 256Mi memory request Β· 500m / 512Mi limits
- Frontend β 50m CPU / 64Mi memory request Β· 100m / 128Mi limits
- Session affinity (
ClientIP) for consistent session routing
Authentication β /api/auth
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/api/auth/register |
β | Register new user (inactive by default) |
POST |
/api/auth/login |
β | Login with username + password |
GET |
/api/auth/me |
User | Get current authenticated user |
POST |
/api/auth/logout |
User | Logout and destroy session |
GET |
/api/auth/users |
Master | List all users |
GET |
/api/auth/users/search?q=term |
Master | Search users by username, name, or email |
POST |
/api/auth/activate |
Master | Activate user accounts |
POST |
/api/auth/deactivate |
Master | Deactivate user accounts |
POST |
/api/auth/change-role |
Master | Change user role (MASTER/USER/READER) |
POST |
/api/auth/delete |
Master | Delete a user account |
Query execution β /api/query
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/api/query/execute |
User | Execute query (async) β returns executionId |
GET |
/api/query/status/:id |
User | Poll execution status and results |
POST |
/api/query/cancel/:id |
User | Cancel a running query (own queries, or any as MASTER) |
GET |
/api/query/active |
User | List active executions |
POST |
/api/query/validate |
User | Validate SQL syntax without executing |
Redis manager β /api/redis
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/api/redis/execute |
User | Execute Redis command across clouds |
POST |
/api/redis/validate |
User | Validate Redis command syntax |
GET |
/api/redis/scan |
User | SCAN for keys matching pattern |
POST |
/api/redis/delete-keys |
User | Delete keys matching pattern |
GET |
/api/redis/history |
User | Redis write history with filters |
History β /api/history
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/history |
User | Query history with filters (database, user_id, success, limit, offset) |
GET |
/api/history/:id |
User | Get specific execution details |
Schema β /api/schemas
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/schemas/configuration |
User | Full database + cloud configuration |
GET |
/api/schemas/:database?cloud= |
User | Schemas for a specific database |
Migration verifier β /api/migrations
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/migrations/config |
User | Available environments, databases, path mappings |
GET |
/api/migrations/refs |
User | Recent git branches and tags for autocomplete |
POST |
/api/migrations/analyze |
User | Analyze SQL diff between two refs against read replica |
GET |
/api/migrations/file?ref=&path= |
User | Raw SQL content of a file at a git ref |
POST |
/api/migrations/refresh-repo |
User | Fetch latest changes from git remote |
Health β /health
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/health |
β | Returns { status: "ok", timestamp, uptime } |
| Layer | Implementation |
|---|---|
| SQL injection | Parameterized queries throughout β no string concatenation |
| Authentication | Sessionβbased with HTTPβonly secure cookies (no JWT tokens to leak) |
| Password storage | bcrypt with 10 salt rounds |
| Authorization | Roleβbased middleware on every route |
| Dangerous queries | Serverβside validation + clientβside warnings + password verification |
| Session storage | Redisβbacked, 7βday expiry, SameSite cookies |
| HTTP headers | Helmet (XβFrameβOptions, XβContentβTypeβOptions, XβXSSβProtection) |
| CORS | Whitelist configured origins only |
| Query timeouts | Configurable perβstatement and overall timeouts |
| Blocked operations | DROP/CREATE DATABASE/SCHEMA, ALTER/CREATE/DROP ROLE/USER β blocked for all roles |
| Migration safety | Readβonly replicas + default_transaction_read_only=on + execFileSync (no shell injection) + path validation |
Backend (cd backend)
| Command | Description |
|---|---|
npm run dev |
Start with hot reload (nodemon + tsx, port 3000) |
npm run build |
Compile TypeScript to dist/ |
npm start |
Run production build |
npm run lint |
Lint with ESLint |
npm test |
Run tests with Vitest |
Frontend (cd frontend)
| Command | Description |
|---|---|
npm run dev |
Vite dev server (port 5173) |
npm run build |
Typeβcheck + production build |
npm run preview |
Preview production build locally |
npm run lint |
Lint with ESLint |
dual-db-manager/
βββ backend/
β βββ config/
β β βββ databases.json ββ Database connection config
β βββ migrations/
β β βββ 001_prod_schema.sql ββ Schema migrations
β βββ src/
β β βββ config/
β β β βββ database.ts ββ Connection pool management
β β βββ controllers/ ββ Route handlers
β β βββ middleware/ ββ Auth, validation, error handling
β β βββ routes/ ββ Express routes
β β βββ services/ ββ Query execution, history, validation
β β β βββ migrations/ ββ Git diff, SQL parser, DB verification
β β βββ types/ ββ TypeScript interfaces
β β βββ utils/ ββ Logger
β β βββ server.ts ββ Entry point
β βββ Dockerfile
β βββ CONFIG.md ββ Configuration reference
βββ frontend/
β βββ src/
β β βββ components/
β β β βββ Dialog/ ββ Warning / confirmation dialogs
β β β βββ Editor/ ββ Monaco SQL editor
β β β βββ History/ ββ Query history sidebar
β β β βββ Migrations/ ββ Migration verifier (results, toolbar, summary, action bar)
β β β βββ Results/ ββ Multiβcloud results panel
β β β βββ Selector/ ββ Database / schema / mode selector
β β βββ hooks/ ββ Autoβsave hook
β β βββ pages/ ββ Login, Console, Users
β β βββ services/ ββ API client, query validation
β β βββ store/ ββ Zustand state management
β β βββ types/ ββ TypeScript interfaces
β βββ nginx.conf ββ Production Nginx config
β βββ Dockerfile
βββ k8s/ ββ Kubernetes manifests
β βββ backend.yaml
β βββ frontend.yaml
β βββ secrets.yaml.example
βββ LICENSE
βββ README.md
1. Fork the repository
2. Create a feature branch git checkout -b feature/my-feature
3. Make your changes
4. Run linting cd backend && npm run lint
cd frontend && npm run lint
5. Commit git commit -m "Add my feature"
6. Push git push origin feature/my-feature
7. Open a Pull Request
MIT License β see LICENSE for details.
Built for teams managing PostgreSQL across multiple clouds.
{ "primary": { "cloudName": "cloud1", "db_configs": [ { "name": "mydb", "label": "My Database", "host": "localhost", "port": 5432, "user": "postgres", "password": "password", "database": "mydb", "schemas": ["public"], "defaultSchema": "public" } ] }, "secondary": [ { "cloudName": "cloud2", "db_configs": [ { "name": "mydb", "label": "My Database", "host": "remote-host", "port": 5432, "user": "postgres", "password": "${CLOUD2_DB_PASSWORD}", "database": "mydb", "schemas": ["public"], "defaultSchema": "public" } ] } ], "history": { "host": "localhost", "port": 5432, "user": "postgres", "password": "password", "database": "mydb" } }