A collaborative file storage and document editing platform — functionally equivalent to Google Drive + Google Docs. Built as a polyglot microservices system to demonstrate a realistic enterprise technology stack.
- Docker and Docker Compose v2+
- ~12 GB of available RAM (for running all infrastructure and services locally)
- GNU Make (optional, for shorthand commands)
- Runs on both x86_64 and Apple Silicon (ARM64) — no Rosetta required
Individual service development may also require the language toolchains listed in the Services table below.
# Start infrastructure (Postgres, Redis, LocalStack, MeiliSearch, observability stack)
make infra-up
# Start all application services (builds images on first run)
make up
# Open the app
open http://localhost:3000 # Web App (React / Next.js)
open http://localhost:4200 # Admin Dashboard (Angular)Or without Make:
docker compose -f docker-compose.infra.yml up -d
docker compose -f docker-compose.infra.yml -f docker-compose.yml up -d --buildOn first run, scripts/init-db.sql creates the required Postgres databases and scripts/localstack-init.sh provisions S3 buckets, SQS queues, SNS topics, and DynamoDB tables in LocalStack automatically.
To stop everything:
make down| Service | Language | Framework | Port | Description |
|---|---|---|---|---|
| API Gateway | Go 1.22 | Chi | 8080 | Request routing, rate limiting, JWT validation |
| Auth Service | Java 17 | Spring Boot 3 | 8081 | Authentication, authorization, user management |
| File Service | Rust 1.77 | Actix-Web 4 | 8082 | File upload/download, S3 integration, versioning |
| Document Service | Python 3.12 | FastAPI | 8083 | Document CRUD, version history, snapshots |
| Collaboration Service | Node.js 20 | Socket.io | 8084 (HTTP) / 8085 (WS) | Real-time collaborative editing (CRDT via Yjs) |
| Notification Service | Kotlin 1.9 | Ktor 2.3 | 8086 | Event-driven notifications (email, in-app, webhook) |
| Search Service | Python 3.12 | Flask 3.0 | 8087 | Full-text search via MeiliSearch |
| Analytics Service | Scala 3.4 | Akka HTTP | 8088 | Usage analytics, data aggregation |
| Admin Service | Ruby 3.3 | Rails 7.1 | 8089 | Admin dashboard backend |
| Audit Service | C# 12 | ASP.NET 8 | 8090 | Immutable audit trail, compliance |
| Report Service (legacy) | Java 8 | Spring Boot 2.5 | 8091 | PDF/CSV/Excel report generation (tech-debt: upgrade target Java 17+, Spring Boot 3.2+) |
Note: The Report Service intentionally uses outdated dependencies (Java 8, Spring Boot 2.5, JUnit 4, javax.*) and is a candidate for a framework-upgrade exercise. See
services/report-service/pom.xmlfor details.
| App | Framework | Port | Description |
|---|---|---|---|
| Web App | React 18 / Next.js 14 | 3000 | Main user-facing application |
| Admin Dashboard | Angular 17 | 4200 | Administrative interface |
See ARCHITECTURE.md for the full system design, data flow, and infrastructure details.
Managed via Terraform in infrastructure/terraform/:
- S3 (file storage, data lake, static assets)
- RDS PostgreSQL
- ElastiCache Redis
- DynamoDB (file metadata, audit events, notifications)
- SQS/SNS (event bus)
- MeiliSearch (full-text search)
- Cognito (identity federation)
- CloudFront (CDN)
- ECR (container image repositories)
- Helm charts per service in
infrastructure/helm/ - Base namespace resources (ResourceQuota, LimitRange) in
infrastructure/k8s/ - Deploys to EKS cluster managed by platform-engineering-shared-services
# Initialize and apply Terraform
make tf-init
make tf-apply # uses environments/dev.tfvars
# Deploy services to EKS
make deploy-devmake teardown-devAll observability services run locally via docker-compose.infra.yml.
| Tool | URL | Purpose |
|---|---|---|
| Grafana | http://localhost:3001 | Dashboards and metrics visualization (admin / otterworks) |
| Prometheus | http://localhost:9090 | Metrics collection and alerting rules |
| Jaeger | http://localhost:16686 | Distributed tracing UI |
| MeiliSearch | http://localhost:7700 | Search engine dashboard |
- Logging: Structured JSON logs → Fluent Bit → CloudWatch (production) / stdout (local)
- Metrics: Prometheus scraping
/metricsendpoints + Grafana dashboards inobservability/grafana/dashboards/ - Tracing: OpenTelemetry SDK per service → OTel Collector → Jaeger
- Alerting: PrometheusRule definitions in
observability/prometheus/→ Alertmanager
GitHub Actions workflows in .github/workflows/:
| Workflow | Trigger | Description |
|---|---|---|
ci.yml |
Push / PR to main |
Lint, test, and build changed services (change-detection via path filters) |
docker-build.yml |
Push to main / tags |
Build and push Docker images to ECR |
security-scan.yml |
Push / PR | SAST, dependency audit, and container scanning |
Run make help to list all available commands. Key targets:
| Command | Description |
|---|---|
make infra-up |
Start local infrastructure (Postgres, Redis, LocalStack, MeiliSearch, observability) |
make up |
Build and start all application services |
make down |
Stop all services and infrastructure |
make build |
Build all service Docker images |
make logs |
Tail logs for all services |
make test |
Run tests for all services |
make lint |
Lint all services |
make tf-plan |
Plan Terraform changes (dev) |
make deploy-dev |
Deploy all services to dev EKS |
make teardown-dev |
Tear down the dev environment |
Per-service build targets are also available (e.g., make build-gateway, make build-auth).
otterworks/
├── services/ # Backend microservices (11 services, 8 languages)
│ ├── api-gateway/ # Go / Chi
│ ├── auth-service/ # Java / Spring Boot
│ ├── file-service/ # Rust / Actix-Web
│ ├── document-service/ # Python / FastAPI
│ ├── collab-service/ # Node.js / Socket.io
│ ├── notification-service/ # Kotlin / Ktor
│ ├── search-service/ # Python / Flask
│ ├── analytics-service/ # Scala / Akka HTTP
│ ├── admin-service/ # Ruby / Rails
│ ├── audit-service/ # C# / ASP.NET
│ └── report-service/ # Java 8 / Spring Boot 2.5 (legacy)
├── frontend/ # Web app (React/Next.js) + Admin dashboard (Angular)
├── infrastructure/
│ ├── terraform/ # App-specific AWS resources (S3, RDS, DynamoDB, etc.)
│ ├── helm/ # Per-service Helm charts
│ └── k8s/ # Base Kubernetes resources (namespace, quotas, limits)
├── shared/
│ ├── proto/ # Protobuf / gRPC service definitions
│ ├── openapi/ # OpenAPI specs per service
│ └── events/ # Event schema definitions (JSON Schema)
├── observability/
│ ├── grafana/ # Dashboards and provisioning
│ ├── prometheus/ # Scrape config, alert rules, recording rules
│ ├── jaeger/ # Jaeger deployment config
│ ├── otel/ # OpenTelemetry Collector config
│ └── logging/ # Fluent Bit config and parsers
├── security/
│ ├── policies/ # Network policies (default-deny, DNS, namespace egress)
│ └── scanning/ # Trivy container scanning config
├── etl/
│ ├── airflow/ # Airflow DAGs, plugins, and tests
│ └── spark/ # Scala Spark processing jobs
├── scripts/ # Deploy and teardown scripts
└── .github/workflows/ # CI/CD pipelines (ci, docker-build, security-scan)
- Fork the repository and create a feature branch from
main. - Follow the Quick Start instructions to bring up the local environment.
- Make your changes in the relevant service or module directory.
- Each service follows the idiomatic conventions of its language (e.g.,
go fmt,cargo clippy,ruff,eslint). - Run
make lintbefore committing to catch issues early. - Run
make testto execute the full test suite.
- Use clear, descriptive commit messages.
- Keep commits focused — one logical change per commit.
- Push your branch and open a PR against
main. - Ensure CI passes (lint, test, build, security scan).
- Include a concise description of what changed and why.
- Link to any relevant issue or user story.
- Create a directory under
services/<service-name>/with aDockerfile. - Add the service to
docker-compose.ymlwith the shared environment block (x-common-env). - Create a Helm chart in
infrastructure/helm/<service-name>/. - Add OpenAPI and event schemas to
shared/. - Update this README and
ARCHITECTURE.md.
Proprietary - OtterWorks Inc.