Build the same chat feature with three different tech stacks from a single specification
This tutorial demonstrates SDD’s power to generate multiple implementations from a single specification. You’ll create a real-time chat feature and explore it with Python/FastAPI, Go/Gin, and Rust/Axum—all from one technology-agnostic spec.
Time to complete: 60-90 minutesWhat you’ll build: Chat feature with 3 parallel implementationsPrerequisites: Comfortable with SDD workflow, completed greenfield tutorial
You’re architecting a real-time chat system and need to evaluate different backend technologies. Rather than building prototypes from scratch or relying on theoretical comparisons, you want working implementations to compare:
Specifications transcend technology. If done right, a single spec can generate functionally equivalent implementations in different languages and frameworks.
Benefits:
Apples-to-apples comparison: Same features, different tech
De-risk technology choices: Try before you commit
Platform-specific optimizations: Tailor to different constraints
Organizational flexibility: Teams can choose preferred stack
Define principles that apply to all implementations:
/speckit.constitution Create technology-agnostic principles that apply regardless of programming language:1. All implementations MUST provide identical REST API contracts2. WebSocket protocol MUST be compatible across all versions3. Performance target: <50ms p95 latency for message delivery4. Security: JWT authentication with same token format5. Data format: JSON for all API responses6. Observability: Structured logging with consistent schema7. Testing: Minimum 80% code coverage for all implementations8. Each implementation MUST be independently deployable
Generated constitution:
Technology-Agnostic Constitution
# Chat System Constitution## Principles### Article I: API Contract ConsistencyAll implementations MUST expose identical REST and WebSocket APIs.**Rules:**- Same endpoint paths (`/api/v1/messages`, `/ws/chat`)- Same request/response JSON schemas- Same HTTP status codes for errors- Same WebSocket message formats**Rationale**: Clients should not need to know which backend they're using.**Validation**: OpenAPI spec defines contract; implementations tested against it.### Article II: Performance ParityAll implementations MUST meet the same performance targets.**Rules:**- Message delivery: <50ms p95 latency- WebSocket connections: Support 1,000 concurrent- Memory usage: <100MB for 1,000 connections- Startup time: <5 seconds**Rationale**: Fair comparison requires similar performance characteristics.**Validation**: Load tests with same test harness (k6 or Locust).### Article III: Security EquivalenceAll implementations MUST provide equivalent security.**Rules:**- JWT authentication with HS256 algorithm- Same token structure and claims- Same token expiration (24 hours)- HTTPS enforced in production**Rationale**: Security cannot be compromised for any stack.**Validation**: Security tests verify JWT validation logic.### Article IV: Observability StandardsAll implementations MUST produce compatible logs and metrics.**Rules:**- Structured JSON logs- Same log fields: timestamp, level, message, trace_id- Prometheus metrics with same names- Health check endpoint: GET /health**Rationale**: Consistent observability enables fair operational comparison.**Validation**: Log parsers validate JSON structure.### Article V: Independent DeployabilityEach implementation MUST be self-contained and deployable.**Rules:**- Dockerfile for each implementation- No shared runtime dependencies- Same PostgreSQL schema (can share DB or use separate)- Environment variables for configuration**Rationale**: Real-world deployment must be considered.**Validation**: Deploy all three to same Kubernetes cluster.
Critical: Specification must be completely technology-agnostic.
/speckit.specify Build a real-time chat feature where users can:1. Send text messages to channels (rooms)2. See messages from other users in real-time3. See typing indicators when others are composing messages4. View message history (last 100 messages per channel)5. Create new channels and join existing channels6. See who is currently in a channel (presence)Users authenticate with a username and receive a session token. Messages include sender name, timestamp, and text content. Channels have a unique name and can be public (anyone can join) or private (invite-only). Typing indicators show "<username> is typing..." and disappear after 3 seconds of inactivity. Message history is loaded when joining a channel. Presence updates when users join/leave channels or disconnect.The system must handle 1,000 concurrent users across 100 channels, deliver messages with <50ms latency, and maintain connection stability. Messages must persist to a database. Authentication tokens expire after 24 hours.
What happens:
1
AI generates spec
Creates specs/001-chat-feature/spec.md with no technology references
2
Validates technology-agnosticism
Checklist ensures no languages, frameworks, or libraries mentioned
3
Creates API contracts
Generates OpenAPI spec that all implementations must satisfy
## Functional Requirements- **FR-001**: System MUST authenticate users via username/password- **FR-002**: System MUST issue session tokens valid for 24 hours- **FR-003**: System MUST persist messages to a database- **FR-004**: System MUST deliver messages to channel members in <50ms p95- **FR-005**: System MUST support 1,000 concurrent WebSocket connections- **FR-006**: System MUST show typing indicators within 500ms- **FR-007**: System MUST update presence within 1 second of join/leave## API Contracts### REST API**POST /api/v1/auth/login**Request:```json{"username": "string", "password": "string"}
SC-003: Memory usage under 100MB at 1,000 connections
SC-004: Typing indicators appear within 500ms
SC-005: Presence updates within 1 second
SC-006: 100% API contract compliance (all implementations)
<Note> The specification defines **what** (functionality, API contracts, performance) without **how** (technology choices). This is crucial for parallel implementations.</Note>## Step 4: Generate Three Implementation PlansNow comes the key divergence: create **three separate plans** from the same spec.### Implementation 1: Python/FastAPI```text/speckit.plan --output specs/001-chat-feature/plan-python.mdImplement using Python 3.11 with FastAPI for REST API and WebSockets. Use PostgreSQL for message persistence with asyncpg driver. Use Redis for pub/sub to coordinate WebSocket messages across multiple workers. Use Pydantic for data validation. Use pytest for testing.
/speckit.plan --output specs/001-chat-feature/plan-go.mdImplement using Go 1.21 with Gin framework for REST API and Gorilla WebSocket for WebSocket support. Use PostgreSQL with pgx driver. Use Redis for pub/sub. Use Go channels for internal message passing between goroutines. Use testify for testing.
/speckit.plan --output specs/001-chat-feature/plan-rust.mdImplement using Rust 1.74 with Axum framework for REST API and WebSocket support. Use PostgreSQL with sqlx for compile-time checked queries. Use Redis for pub/sub via redis-rs. Use Tokio for async runtime. Use tokio channels for message passing. Use cargo test for testing.
# Python implementationBASE_URL=http://localhost:8000 WS_URL=ws://localhost:8000 k6 run performance-test.js# Go implementationBASE_URL=http://localhost:8080 WS_URL=ws://localhost:8080 k6 run performance-test.js# Rust implementationBASE_URL=http://localhost:3000 WS_URL=ws://localhost:3000 k6 run performance-test.js