Local Development Environment
This guide covers how to run the full Ngwenya Federation stack locally for development. The platform uses Podman as its container engine (with Docker as a fallback) to orchestrate 20+ microservices, databases, and infrastructure components.
Prerequisites
| Tool | Version | Install |
|---|---|---|
| Podman | 5.8+ | brew install podman podman-compose |
| Node.js | 25+ | brew install node |
| pnpm | 9+ | npm i -g pnpm |
| Rust | 1.89+ | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| SQLx CLI | 0.8+ | cargo install sqlx-cli --no-default-features --features postgres,native-tls |
Podman Machine Setup
Podman on macOS runs containers inside a lightweight Linux VM. Configure it with enough resources for the full stack:
# Initialize with generous resources (one-time)
podman machine init --cpus 8 --memory 16384 --disk-size 200
# Start the VM
podman machine start
The VM is configured with:
- 8 CPUs โ parallel builds across NestJS and Rust services
- 16 GB RAM โ required for building 15+ services concurrently
- 200 GB disk โ accommodates Docker images, build cache, and database volumes
Why Podman over Docker Desktop? Podman gives direct control over VM resources without the artificial memory/disk limits that Docker Desktop imposes. On a 4 TB SSD, Docker Desktop may still cap its virtual disk at 64โ100 GB. Podman also runs daemonless, reducing system overhead.
Switching Between Engines
The Makefile uses a configurable CONTAINER_CMD variable:
# Default: Podman
make dev
# Override to Docker
make dev CONTAINER_CMD=docker
# Check active engine
make help
Architecture Overview
The federation runs as a Docker Compose stack with three layers:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ngwenya-gateway โ
โ (Hive Gateway / Yoga) โ
โ :30000 โ
โโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโค
โ malets โproductsโservicesโ ucart โ ... 10 more โ
โ :3001 โ :3004 โ :3003 โ :3005 โ NestJS svcs โ
โโโโโโโโโโดโโโโโโโโโผโโโโโโโโโดโโโโโโโโโผโโโโโโโโโโโโโโโค
โ auth โ uchat โ Rust svcs โ
โ :3008 โ :3017/:3018 โ โ
โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโค
โ postgres โ redis โ mongo โ meilisearch โ
โ :5432 โ :6379 โ :27017 โ :7700 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Service Categories
| Layer | Services | Technology |
|---|---|---|
| Gateway | ngwenya-gateway |
Hive Gateway, GraphQL Yoga, Federation |
| NestJS Subgraphs | malets, products, services, ucart, media, blogs, community, organizations, nodes, murchases, payments, search, alerts, experiences | NestJS + MongoDB |
| Rust Services | auth, uchat | Axum + PostgreSQL |
| Infrastructure | postgres, redis, mongo, meilisearch, conduit (Matrix) | Managed images |
Database Separation
Each Rust service has its own PostgreSQL database to prevent migration collisions:
| Service | Database | Migrations |
|---|---|---|
| auth | ngwenya_auth |
Timestamp-based (SQLx) |
| uchat | ngwenya_uchat |
Sequential (001โ008) |
The ngwenya_uchat database is auto-created on first boot via an init script mounted at /docker-entrypoint-initdb.d/.
Make Targets
Run make help for the full list. Key targets:
Starting Services
# Start all services (Podman Compose)
make dev
# Full nuke + rebuild (wipes volumes)
make clean-dev
# Infrastructure only (DBs, Redis, Meilisearch, Conduit)
make infra-up
Native Development (Fastest Iteration)
For rapid iteration on Rust services, run them natively against Podman's databases:
# Start infra in Podman, NestJS services natively
make services
# Rebuild and restart just uchat (6s vs 90s Docker rebuild)
make restart-uchat
# Rebuild and restart just auth
make restart-auth
Testing
# All unit tests
make test
# E2E tests (all services)
make test-e2e
# E2E tests for a specific subgraph
make test-e2e PATTERN=payments
# Tests for a specific subgraph (unit + E2E)
make test-all-pattern PATTERN=payments
# All Pact contract tests
make test-pact
# Soak test (sustained load + memory monitoring)
make soak-test # Full 30-min run
SOAK_DURATION_MINS=5 make soak-test # Quick 5-min validation
Database Operations
# Seed with sample data
make seed
# Bulk seed (10 Malets ร 100 items)
make seed-bulk
# Clean + re-seed
make seed-reset
# Rebuild Meilisearch index
make search-reindex
Development Workflows
Workflow 1: Full-Stack (New Developer)
Best for first-time setup or integration testing:
# 1. Clone and set up
git clone <repo> && cd ngwenya-federation
cp apps/auth/.env.example apps/auth/.env
# 2. Initialize Podman (one-time)
podman machine init --cpus 8 --memory 16384 --disk-size 200
podman machine start
# 3. Build and start everything
make clean-dev
# 4. Verify
curl -s -X POST -H "Content-Type: application/json" \
-d '{"query":"{__typename}"}' \
http://localhost:30000/graphql
Workflow 2: Iterating on a Rust Service (Recommended Daily)
Best for active development on uchat or auth:
# 1. Ensure infra is running (Podman)
make infra-up
# 2. Make your code changes
# ... edit apps/uchat/src/...
# 3. Rebuild and restart natively (fast!)
make restart-uchat
# 4. Test
cargo test -p uchat
Workflow 3: NestJS Subgraph Work
# 1. Start everything
make dev
# 2. Watch logs for your service
podman compose -f docker-compose-dev.yaml logs -f malets
# Or run natively with hot-reload
make services
Workflow 4: Frontend Development (All 5 Apps)
The frontend uses a pnpm workspace that links the Storefront, Tower, Deck, and shared packages:
# 1. Install workspace dependencies from the monorepo root
cd ngwenya && pnpm install
# Or from ngwenya-front:
cd ngwenya-front && make install
# 2. Start all 5 frontend apps simultaneously
make ui
# This starts:
# - Storefront localhost:5173
# - Tower localhost:5170
# - Deck localhost:5171
# - Developer Portal localhost:4321
# - Support Center localhost:4322
# 3. Or start individual apps
make tower-ui # Tower only
make deck-ui # Deck only
make dev-portal # Developer docs only
All three SvelteKit apps (Storefront, Tower, Deck) share the @ngwenya/queries workspace package for GraphQL operations. The make install target runs pnpm install from the workspace root to resolve workspace:* dependencies.
IMPORTANT
All three frontend apps run on Vite 8 (Rolldown) with Svelte 5 and SvelteKit 2. Version parity is critical โ do not upgrade individual app versions without aligning all three.
Troubleshooting
`no space left on device`
Docker/Podman VM disk is full. Prune unused images and build cache:
podman system prune -a --volumes -f
If it persists, increase the VM disk size:
podman machine rm -f
podman machine init --cpus 8 --memory 16384 --disk-size 300
podman machine start
`cannot allocate memory` during builds
The VM doesn't have enough RAM. The default Podman machine ships with only 2 GB. Recreate with at least 16 GB:
podman machine rm -f
podman machine init --memory 16384
podman machine start
Conduit shows `unhealthy`
The Matrix homeserver (Conduit) may show as unhealthy if curl or wget is not available in its container image. This is cosmetic โ Conduit itself is running fine. The uchat service handles Matrix disconnection gracefully and will retry on startup.
uchat migration errors (`VersionMissing`)
This happens when uchat connects to the wrong database (e.g., ngwenya_auth instead of ngwenya_uchat). Verify the DATABASE_URL in docker-compose-dev.yaml points to ngwenya_uchat:
uchat:
environment:
DATABASE_URL: postgres://postgres:password@postgres:5432/ngwenya_uchat
`.dockerignore` and Build Context
Each Rust service has its own .dockerignore to exclude the multi-GB target/ directory from the build context. Without this, Docker/Podman tries to upload 5โ14 GB of build artifacts into the container, causing disk exhaustion:
# apps/uchat/.dockerignore
target/
.env
.env.local
*.log
Related
- Gateway (Hive Gateway) โ Federated gateway architecture, composition, and benchmarks
- Debugging & Testing โ Manual debug workflows for verifying auth context and data consistency
- E2E Testing Infrastructure โ Playwright-based end-to-end testing architecture for the frontend
- Vertical Seeding Infrastructure โ Multi-tenant vertical seeding for 11 storefronts with
make seed-verticals - Documentation Portal Architecture โ Standalone Astro doc portals, env-driven URLs, and
make uiorchestration - Error Tracking (GlitchTip) โ Self-hosted crash reporting โ
make glitchtip-upto start the error dashboard - Database Backup & Disaster Recovery โ Pluggable backup/restore, local cron, and cloud storage backends
- Staging Environment Architecture โ Contrast local development with the multi-repo pre-production environment