368 lines
8.2 KiB
Markdown
368 lines
8.2 KiB
Markdown
# Milestone 2: Web Stack Selection
|
|
|
|
**Status**: Decided
|
|
**Goal**: Choose backend technologies for the developer portal and app store API.
|
|
|
|
## Decision
|
|
|
|
**Go** with the following stack:
|
|
|
|
```
|
|
Language: Go 1.22+
|
|
Framework: Chi (lightweight, idiomatic)
|
|
Database: SQLite via modernc.org/sqlite (pure Go, no CGO)
|
|
Migrations: golang-migrate
|
|
Validation: go-playground/validator
|
|
Auth: Custom JWT + OAuth2
|
|
Deployment: Single Docker container on Synology NAS
|
|
```
|
|
|
|
### Rationale
|
|
|
|
1. **NAS-friendly** - Tiny Docker image (~15MB), low RAM (~30-50MB)
|
|
2. **Cross-compilation** - Easy build for ARM64 or AMD64 Synology models
|
|
3. **Pure Go SQLite** - `modernc.org/sqlite` requires no CGO, cross-compiles easily
|
|
4. **Single container** - Go binary + SQLite + Litestream in one image
|
|
5. **Standard library** - HTTP, JSON, crypto all built-in
|
|
|
|
### Target Deployment
|
|
|
|
```
|
|
Synology NAS (Docker)
|
|
├── mosis-portal container (~15MB image)
|
|
│ ├── Go binary
|
|
│ ├── SQLite database (WAL mode)
|
|
│ └── Litestream backup
|
|
└── Volumes
|
|
├── /volume1/mosis/data/portal.db
|
|
├── /volume1/mosis/backups/
|
|
└── /volume1/mosis/packages/
|
|
```
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
The web stack powers the developer portal, app store API, and telemetry ingestion. This decision affects development speed, hosting costs, and long-term maintenance.
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
### Functional
|
|
|
|
- REST API for developer portal
|
|
- File upload handling (app packages)
|
|
- Authentication (OAuth2, API keys)
|
|
- Database integration
|
|
- Background jobs (review queue, notifications)
|
|
- WebSocket support (optional, for real-time updates)
|
|
|
|
### Non-Functional
|
|
|
|
- Handle 1000+ developers initially
|
|
- Scale to 10,000+ apps
|
|
- 99.9% uptime target
|
|
- < 200ms API response time (p95)
|
|
- Secure by default
|
|
|
|
---
|
|
|
|
## Options Analysis
|
|
|
|
### Option A: Node.js + TypeScript
|
|
|
|
#### Stack
|
|
```
|
|
Runtime: Node.js 20 LTS
|
|
Language: TypeScript
|
|
Framework: Fastify or Hono
|
|
ORM: Prisma or Drizzle
|
|
Validation: Zod
|
|
Auth: Lucia or custom JWT
|
|
```
|
|
|
|
#### Pros
|
|
| Advantage | Details |
|
|
|-----------|---------|
|
|
| Fast development | Large ecosystem, familiar syntax |
|
|
| Type safety | TypeScript catches errors early |
|
|
| Easy hiring | Many JS/TS developers |
|
|
| Ecosystem | npm has libraries for everything |
|
|
| Hosting | Vercel, Railway, Render, any VPS |
|
|
|
|
#### Cons
|
|
| Disadvantage | Details |
|
|
|--------------|---------|
|
|
| Single-threaded | Need clustering for CPU tasks |
|
|
| Memory usage | Higher than compiled languages |
|
|
| Callback complexity | Async can get messy |
|
|
|
|
#### Example Structure
|
|
```
|
|
src/
|
|
├── index.ts
|
|
├── routes/
|
|
│ ├── auth.ts
|
|
│ ├── apps.ts
|
|
│ └── telemetry.ts
|
|
├── services/
|
|
│ ├── auth.service.ts
|
|
│ └── storage.service.ts
|
|
├── db/
|
|
│ ├── schema.ts
|
|
│ └── client.ts
|
|
└── utils/
|
|
```
|
|
|
|
#### Hosting Cost Estimate
|
|
| Service | Cost/month |
|
|
|---------|------------|
|
|
| Railway (starter) | $5-20 |
|
|
| Vercel Pro | $20 |
|
|
| VPS (4GB) | $20-40 |
|
|
|
|
---
|
|
|
|
### Option B: Go
|
|
|
|
#### Stack
|
|
```
|
|
Language: Go 1.22+
|
|
Framework: Chi, Echo, or Gin
|
|
ORM: sqlc or GORM
|
|
Validation: go-playground/validator
|
|
Auth: Custom JWT
|
|
```
|
|
|
|
#### Pros
|
|
| Advantage | Details |
|
|
|-----------|---------|
|
|
| Performance | Fast, low memory |
|
|
| Single binary | Easy deployment |
|
|
| Concurrency | Goroutines handle load well |
|
|
| Standard library | HTTP, JSON, crypto built-in |
|
|
|
|
#### Cons
|
|
| Disadvantage | Details |
|
|
|--------------|---------|
|
|
| Verbose | Error handling boilerplate |
|
|
| Smaller ecosystem | Fewer ready-made solutions |
|
|
| Learning curve | Different paradigm |
|
|
|
|
#### Example Structure
|
|
```
|
|
cmd/
|
|
├── server/
|
|
│ └── main.go
|
|
internal/
|
|
├── api/
|
|
│ ├── handlers/
|
|
│ ├── middleware/
|
|
│ └── routes.go
|
|
├── domain/
|
|
│ ├── app.go
|
|
│ └── developer.go
|
|
├── repository/
|
|
│ └── postgres/
|
|
└── service/
|
|
```
|
|
|
|
#### Hosting Cost Estimate
|
|
| Service | Cost/month |
|
|
|---------|------------|
|
|
| Fly.io (shared) | $5-15 |
|
|
| Cloud Run | Pay per use |
|
|
| VPS (2GB) | $10-20 |
|
|
|
|
---
|
|
|
|
### Option C: Rust + Axum
|
|
|
|
#### Stack
|
|
```
|
|
Language: Rust
|
|
Framework: Axum
|
|
ORM: sqlx or SeaORM
|
|
Validation: validator crate
|
|
Auth: Custom JWT
|
|
```
|
|
|
|
#### Pros
|
|
| Advantage | Details |
|
|
|-----------|---------|
|
|
| Maximum performance | Fastest option |
|
|
| Memory safety | No runtime errors |
|
|
| Single binary | Easy deployment |
|
|
| Long-term reliability | Compiler catches bugs |
|
|
|
|
#### Cons
|
|
| Disadvantage | Details |
|
|
|--------------|---------|
|
|
| Steep learning curve | Borrow checker takes time |
|
|
| Slower development | More code to write |
|
|
| Smaller ecosystem | Fewer web libraries |
|
|
| Compile times | Can be slow |
|
|
|
|
#### Example Structure
|
|
```
|
|
src/
|
|
├── main.rs
|
|
├── api/
|
|
│ ├── mod.rs
|
|
│ ├── handlers/
|
|
│ └── middleware/
|
|
├── domain/
|
|
├── repository/
|
|
└── service/
|
|
```
|
|
|
|
#### Hosting Cost Estimate
|
|
| Service | Cost/month |
|
|
|---------|------------|
|
|
| Fly.io | $5-10 |
|
|
| Shuttle | Free tier available |
|
|
| VPS (1GB) | $5-10 |
|
|
|
|
---
|
|
|
|
### Option D: .NET (ASP.NET Core)
|
|
|
|
#### Stack
|
|
```
|
|
Language: C#
|
|
Framework: ASP.NET Core 8
|
|
ORM: Entity Framework Core
|
|
Validation: FluentValidation
|
|
Auth: ASP.NET Identity
|
|
```
|
|
|
|
#### Pros
|
|
| Advantage | Details |
|
|
|-----------|---------|
|
|
| Enterprise-ready | Battle-tested at scale |
|
|
| Great tooling | Visual Studio, debugging |
|
|
| Performance | Very fast (Kestrel) |
|
|
| Full-featured | Auth, validation, DI built-in |
|
|
|
|
#### Cons
|
|
| Disadvantage | Details |
|
|
|--------------|---------|
|
|
| Heavier runtime | Larger container images |
|
|
| Microsoft ecosystem | May feel locked in |
|
|
| Verbose | More boilerplate |
|
|
|
|
#### Hosting Cost Estimate
|
|
| Service | Cost/month |
|
|
|---------|------------|
|
|
| Azure App Service | $15-50 |
|
|
| VPS (4GB) | $20-40 |
|
|
|
|
---
|
|
|
|
## Evaluation Matrix
|
|
|
|
| Criteria | Weight | Node.js | Go | Rust | .NET |
|
|
|----------|--------|---------|-----|------|------|
|
|
| Dev speed | 25% | 9 | 7 | 5 | 7 |
|
|
| Performance | 20% | 6 | 9 | 10 | 8 |
|
|
| Hosting cost | 15% | 7 | 9 | 9 | 6 |
|
|
| Ecosystem | 15% | 9 | 7 | 6 | 8 |
|
|
| Team familiarity | 15% | ? | ? | ? | ? |
|
|
| Long-term maintenance | 10% | 7 | 8 | 9 | 8 |
|
|
| **Weighted Score** | | **7.4** | **7.8** | **7.2** | **7.3** |
|
|
|
|
*Team familiarity needs to be filled in based on actual experience*
|
|
|
|
---
|
|
|
|
## Framework Comparison
|
|
|
|
### Node.js Frameworks
|
|
|
|
| Framework | Req/sec | Features | Learning Curve |
|
|
|-----------|---------|----------|----------------|
|
|
| Express | 15k | Minimal, flexible | Easy |
|
|
| Fastify | 45k | Fast, schema validation | Medium |
|
|
| Hono | 50k | Ultra-light, edge-ready | Easy |
|
|
| NestJS | 20k | Full-featured, Angular-like | Steep |
|
|
|
|
### Go Frameworks
|
|
|
|
| Framework | Req/sec | Features | Learning Curve |
|
|
|-----------|---------|----------|----------------|
|
|
| net/http | 60k | Standard library | Medium |
|
|
| Chi | 55k | Lightweight router | Easy |
|
|
| Gin | 50k | Popular, middleware | Easy |
|
|
| Echo | 55k | Similar to Gin | Easy |
|
|
|
|
---
|
|
|
|
## Prototype Plan
|
|
|
|
### Phase 1: Build minimal API in top 2 choices
|
|
|
|
Endpoints to implement:
|
|
```
|
|
POST /auth/register
|
|
POST /auth/login
|
|
GET /apps
|
|
POST /apps
|
|
POST /apps/:id/versions
|
|
```
|
|
|
|
### Phase 2: Benchmark
|
|
|
|
- Requests per second
|
|
- Memory usage under load
|
|
- Development time tracking
|
|
- Code complexity comparison
|
|
|
|
### Phase 3: Decision
|
|
|
|
Based on:
|
|
- Benchmark results
|
|
- Developer experience during prototype
|
|
- Hosting cost analysis
|
|
|
|
---
|
|
|
|
## Recommendation
|
|
|
|
**Primary: Go with Chi/Echo**
|
|
- Best balance of performance and simplicity
|
|
- Low hosting costs
|
|
- Single binary deployment
|
|
- Good enough ecosystem for our needs
|
|
|
|
**Fallback: Node.js with Hono/Fastify**
|
|
- If Go feels too slow to develop in
|
|
- Larger ecosystem for edge cases
|
|
- More developers familiar with it
|
|
|
|
---
|
|
|
|
## Deliverables
|
|
|
|
- [x] Final selection with rationale
|
|
- [ ] Project structure template
|
|
- [ ] Development environment setup guide
|
|
- [ ] Base Go project scaffolding
|
|
|
|
---
|
|
|
|
## Open Questions
|
|
|
|
1. Do we need GraphQL or is REST sufficient?
|
|
2. Do we need real-time features (WebSocket)?
|
|
3. What's the team's current language experience?
|
|
4. Any preference for specific cloud providers?
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- [TechEmpower Benchmarks](https://www.techempower.com/benchmarks/)
|
|
- [Go vs Node.js comparison](https://blog.logrocket.com/node-js-vs-golang/)
|
|
- [Fastify benchmarks](https://fastify.dev/benchmarks/)
|