Multi-Instance Development β
Run multiple instances of the project simultaneously β useful when multiple developers, AI agents, or workflows need to work on different branches without port conflicts or shared database interference.
Each instance gets:
- Its own git worktree (isolated code checkout)
- Its own Docker containers (MongoDB, Redis) with separate data volumes
- Offset ports so nothing conflicts with the main repo or other instances
Port Mapping β
Each instance offsets all ports by N x 100:
| Service | Main | Instance 1 | Instance 2 |
|---|---|---|---|
| Backend API | 3888 | 3988 | 4088 |
| Frontend Vite | 5173 | 5273 | 5373 |
| MongoDB | 27017 | 27117 | 27217 |
| Redis | 6379 | 6479 | 6579 |
| Redis Insight | 5540 | 5640 | 5740 |
| Bull Board | 3001 | 3101 | 3201 |
Create an Instance β
From the main repo root:
./scripts/create-instance.sh 1This will:
- Create a git worktree at
../tell-ia-instance-1on branchinstance-1 - Run
pnpm install - Build shared packages (
@tellia-solutions/schemas) - Copy
.envfiles with adjusted ports - Create a
.env.composefile for Docker Compose
Start the Instance β
1. Start infrastructure β
cd ../tell-ia-instance-1/apps/agri-backend
docker compose --env-file .env.compose up -dIMPORTANT
Always use --env-file .env.compose when running docker compose in an instance. The regular .env contains multi-line values that Docker Compose can't parse for variable interpolation.
2. Seed the database β
The instance database starts empty. Populate it from production:
cd ../tell-ia-instance-1/apps/agri-backend
./dev/scripts/create-user-db.shThe script automatically reads MONGODB_URI from the instance's .env and targets the correct port.
You can also specify the target explicitly:
TARGET_MONGODB_URI="mongodb://user:pass@localhost:27117" ./dev/scripts/create-user-db.sh3. Start backend and frontend β
# Terminal 1 β Backend
cd ../tell-ia-instance-1
pnpm --filter agri-backend dev
# Terminal 2 β Frontend
cd ../tell-ia-instance-1
pnpm --filter agri-frontend devConnect to the Instance Database β
Use MongoDB Compass with the instance connection string:
| Instance | Connection String |
|---|---|
| Main | mongodb://user:pass@localhost:27017/?authSource=admin&directConnection=true |
| Instance 1 | mongodb://user:pass@localhost:27117/?authSource=admin&directConnection=true |
| Instance 2 | mongodb://user:pass@localhost:27217/?authSource=admin&directConnection=true |
Dev Tunnels β
Each instance gets a pre-configured frpc.toml with tunnel proxies for the frontend and API. Subdomains follow the pattern {user}-i{N}:
| Instance | Frontend Tunnel | API Tunnel |
|---|---|---|
| Instance 1 | https://yourname-i1.dev.review-time.info | https://yourname-i1-api.dev.review-time.info |
| Instance 2 | https://yourname-i2.dev.review-time.info | https://yourname-i2-api.dev.review-time.info |
Start the tunnel from the instance directory:
cd ../tell-ia-instance-1
frpc -c frpc.tomlThe dev name defaults to $USER. Override it with the DEV_NAME env var:
DEV_NAME=alex ./scripts/create-instance.sh 1See Dev Tunnels for setup instructions (frpc install, FRP_TOKEN).
Check Instance Ports β
View the ports assigned to an instance:
cat ../tell-ia-instance-1/apps/agri-backend/.env.composeSwitching Branches Inside an Instance β
A worktree is a regular git checkout. You can switch to any branch from within it:
cd ../tell-ia-instance-1
git switch some-other-branchWARNING
Two worktrees can't have the same branch checked out at the same time. Git will block you if you try to switch to a branch that's already checked out in another worktree (including the main repo).
Remove an Instance β
From the main repo root:
# Keep database data (Docker volumes preserved)
./scripts/remove-instance.sh 1
# Also delete database data
./scripts/remove-instance.sh 1 --volumesThis stops Docker services, removes the git worktree, and deletes the branch.