Writing Technical Specifications in X402
By X402 Team | Last Updated: February 2026
Direct Answer
Technical specifications in X402 are structured markdown documents that define system requirements, architecture, and implementation details in a version-controlled format, organized by feature or component with clear sections for goals, constraints, design decisions, and acceptance criteria.
Overview
Technical specifications (tech specs) are essential planning documents that bridge the gap between product requirements and implementation. They force clear thinking, enable async collaboration, and create a reference for future decisions.
Why X402 for Technical Specifications?
Version Control Native
- Every spec revision tracked in Git
- Diff between specification versions
- Branch-based spec development
- Review process through pull requests
Markdown Flexibility
- Diagrams with Mermaid
- Code examples inline
- Mathematical notation
- Tables and structured data
Cross-Reference Power
- Link to related specs
- Reference API documentation
- Link to implementation code
- Connect to ADRs (Architecture Decision Records)
Living Documentation
- Update specs as implementation evolves
- Mark deprecated sections
- Add implementation notes
- Track actual vs. planned
When to Write a Tech Spec
Write a spec when:
- ✅ Building a new major feature
- ✅ Making significant architectural changes
- ✅ Designing a new API or service
- ✅ Refactoring a complex system
- ✅ The solution isn't immediately obvious
- ✅ Multiple approaches need evaluation
Skip the spec when:
- ❌ Fixing a simple bug
- ❌ Making a trivial UI change
- ❌ The solution is straightforward
- ❌ It's exploratory prototyping
Technical Specification Structure
Standard Template
# [Feature/System Name] Technical Specification
Direct Answer
[One sentence describing what this spec defines]
Metadata
Status: Draft | In Review | Approved | Implemented | Deprecated
Author: @username
Reviewers: @reviewer1, @reviewer2
Created: YYYY-MM-DD
Last Updated: YYYY-MM-DD
Implementation Status: Not Started | In Progress | Complete
Overview
Background
[Why are we building this? What problem does it solve?]
Goals
- Goal 1
- Goal 2
- Goal 3
Non-Goals
- Explicitly out of scope item 1
- Explicitly out of scope item 2
Success Metrics
- Metric 1: [How measured]
- Metric 2: [How measured]
Requirements
Functional Requirements
- FR-1: [Requirement description]
- FR-2: [Requirement description]
Non-Functional Requirements
- Performance: [Target metrics]
- Scalability: [Scale requirements]
- Reliability: [Uptime targets]
- Security: [Security requirements]
- Accessibility: [A11y requirements]
Constraints
- Technical constraint 1
- Business constraint 2
- Resource constraint 3
Proposed Solution
High-Level Architecture
mermaid
graph TD
A[Component A] --> B[Component B]
B --> C[Component C]
C --> D[Database]
[Explanation of architecture]
Detailed Design
Component 1: [Name]
[Description]
Responsibilities:
- Responsibility 1
- Responsibility 2
Interfaces:
typescript
interface ComponentA {
method1(param: Type): ReturnType;
method2(param: Type): Promise
Implementation Notes:
- Note 1
- Note 2
Component 2: [Name]
[Continue pattern...]
Data Model
typescript
interface User {
id: string;
email: string;
name: string;
role: 'admin' | 'user' | 'viewer';
createdAt: Date;
metadata: Record
Schema:sql
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'user',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
metadata JSONB
);
CREATE INDEX idx_users_email ON users(email); CREATE INDEX idx_users_role ON users(role);
API Design
Endpoint 1: Create User
Request:
http
POST /api/v1/users
Content-Type: application/json
{ "email": "user@example.com", "name": "John Doe", "role": "user" }
Response:http
HTTP/1.1 201 Created
Content-Type: application/json
{ "id": "usr_abc123", "email": "user@example.com", "name": "John Doe", "role": "user", "createdAt": "2024-02-15T10:30:00Z" }
Technology Choices
Decision Choice Alternatives Considered Rationale Database PostgreSQL MySQL, MongoDB Need for ACID transactions, JSON support
Cache Redis Memcached Pub/sub capabilities, data structures
Queue RabbitMQ Kafka, SQS Simpler operational overhead
Alternative Approaches
Alternative 1: [Name]
Description: [How this approach would work]
Pros:
- Pro 1
- Pro 2
Cons:
- Con 1
- Con 2
Decision: Not chosen because [reasoning]
Alternative 2: [Name]
[Continue pattern...]
Security Considerations
Authentication
- [How authentication works]
- [Token management]
Authorization
- [Permission model]
- [Access control]
Data Protection
- [Encryption at rest]
- [Encryption in transit]
- [PII handling]
Threat Model
- Threat 1: [Description]
- Mitigation: [How we address it]
Performance Considerations
Expected Load
- [Requests per second]
- [Concurrent users]
- [Data volume]
Performance Targets
- API Response Time: < 200ms p95
- Database Queries: < 50ms p95
- Page Load: < 2s p95
Optimization Strategies
- Caching strategy
- Database indexing
- Query optimization
- CDN for static assets
Scalability
Horizontal Scaling
- [Which components scale horizontally]
- [Load balancing strategy]
Vertical Scaling
- [Resource requirements]
- [Bottlenecks]
Capacity Planning
- Current: [Metrics]
- 6 months: [Projected metrics]
- 12 months: [Projected metrics]
Implementation Plan
Phase 1: Foundation (Week 1-2)
- [ ] Set up database schema
- [ ] Create base API endpoints
- [ ] Implement authentication
Phase 2: Core Features (Week 3-4)
- [ ] Implement RBAC
- [ ] Build admin dashboard
- [ ] Add session management
Phase 3: Polish (Week 5-6)
- [ ] Performance optimization
- [ ] Security audit
- [ ] Documentation
Dependencies
- Blocked by: [Other work]
- Blocks: [Downstream work]
Testing Strategy
Unit Tests
- Test coverage target: 80%
- Key components to test: [List]
Integration Tests
- API endpoint tests
- Database integration tests
- External service mocks
Performance Tests
- Load testing with [tool]
- Stress testing scenarios
- Benchmark metrics
Security Tests
- Penetration testing
- Security scanning
- Vulnerability assessment
Monitoring & Observability
Metrics
- Request rate (requests/second)
- Error rate (errors/total requests)
- Response time (p50, p95, p99)
- Database query time
Logs
- Application logs: [Format, location]
- Access logs: [Format, location]
- Error logs: [Format, location]
Alerts
- Error rate > 1%: Critical
- Response time > 500ms: Warning
- Database connections > 80%: Warning
Dashboards
- System health overview
- Performance metrics
- Business metrics
Rollout Plan
Feature Flags
feature.oauth.enabled: OAuth 2.0 toggle
feature.rbac.enabled: RBAC toggle
Gradual Rollout
- Internal (Week 1): Engineering team
- Beta (Week 2): 10% of users
- GA (Week 3): 100% of users
Rollback Strategy
- Feature flag disable
- Database migration rollback
- Previous version deployment
Documentation
User Documentation
- [ ] Getting started guide
- [ ] OAuth setup guide
- [ ] RBAC configuration guide
- [ ] Migration guide
Developer Documentation
- [ ] API reference
- [ ] Architecture overview
- [ ] Database schema
- [ ] Deployment guide
Open Questions
- Question 1: [Unanswered question]
- Impact: High | Medium | Low
- Status: Under discussion
- Question 2: [Unanswered question]
- Impact: High | Medium | Low
- Status: Blocked on [reason]
Acceptance Criteria
- [ ] All functional requirements implemented
- [ ] Performance targets met
- [ ] Security requirements satisfied
- [ ] Test coverage > 80%
- [ ] Documentation complete
- [ ] Code review approved
- [ ] Security review passed
- [ ] Load testing passed
References
Practical Example: Real Technical Specification
Here's a complete example for a real feature:
# Real-Time Collaboration System Technical Specification
Direct Answer
This specification defines a WebSocket-based real-time collaboration system enabling multiple users to simultaneously edit documents with conflict resolution, presence indicators, and collaborative cursors.
Metadata
Status: Approved
Author: @alice
Reviewers: @bob, @charlie, @diana
Created: 2024-01-15
Last Updated: 2024-02-10
Implementation Status: In Progress (Phase 2 of 3)
Overview
Background
Users currently edit documents in isolation and face "last write wins" conflicts when multiple people work on the same document. This causes data loss and frustration. Support tickets related to lost edits have increased 300% over the past quarter.
Current Pain Points:
- No visibility into who else is editing
- Conflicting edits overwrite each other
- No real-time feedback on changes
- Collaboration requires manual coordination
Goals
- Primary: Enable real-time collaborative editing for up to 10 simultaneous users per document
- Secondary: Provide presence awareness (who's viewing/editing)
- Tertiary: Show collaborative cursors and selections
- Reduce conflict-related support tickets by 80%
- Achieve <100ms latency for edit propagation
Non-Goals
- Video/audio communication (use existing tools like Zoom)
- Chat functionality (separate feature)
- Offline editing sync (future consideration)
- Mobile app support (Phase 2)
- Comment threads (separate feature)
Success Metrics
- Adoption: 40% of active users use collaborative editing within 3 months
- Performance: Edit latency < 100ms p95
- Reliability: 99.9% uptime for WebSocket connections
- Satisfaction: NPS > 8 for collaboration features
- Business: 80% reduction in "lost edit" support tickets
Requirements
Functional Requirements
- FR-1: Users can see who else is viewing/editing a document in real-time
- FR-2: Edits from any user appear to all other users within 100ms
- FR-3: Users see cursor positions and selections of other editors
- FR-4: System handles conflicts using operational transformation or CRDT
- FR-5: Users can see edit history with author attribution
- FR-6: System gracefully handles reconnection after network interruption
- FR-7: Users can see typing indicators showing who is actively editing
Non-Functional Requirements
- Performance:
- Edit propagation latency: < 100ms p95
- WebSocket connection time: < 500ms
- Memory per connection: < 10MB
- CPU per 100 connections: < 20%
- Scalability:
- Support 10,000 concurrent connections per server
- Support 10 simultaneous editors per document
- Handle documents up to 1MB in size
- Reliability:
- 99.9% WebSocket uptime
- Automatic reconnection with exponential backoff
- Zero data loss on connection failures
- Graceful degradation to read-only on server issues
- Security:
- WebSocket authentication via JWT
- Authorization check per document access
- Rate limiting: 100 edits per minute per user
- XSS protection for collaborative content
- Accessibility:
- Screen reader announcements for collaborator joins/leaves
- Keyboard navigation for presence indicators
- High contrast mode for collaborative cursors
Constraints
- Must work with existing PostgreSQL database
- Must not require client-side app updates
- Must support WebSocket protocol (no long polling)
- Maximum server cost increase: 20%
- Must launch within 8 weeks
Proposed Solution
High-Level Architecture
mermaid
graph TB
Client1[Client Browser 1] -->|WebSocket| LB[Load Balancer]
Client2[Client Browser 2] -->|WebSocket| LB
Client3[Client Browser 3] -->|WebSocket| LB
LB --> WS1[WebSocket Server 1] LB --> WS2[WebSocket Server 2]
WS1 <-->|Pub/Sub| Redis[Redis Pub/Sub] WS2 <-->|Pub/Sub| Redis
WS1 --> DB[(PostgreSQL)] WS2 --> DB
WS1 --> Store[Document Store] WS2 --> Store
Flow:
- Client establishes WebSocket connection with JWT authentication
- Client subscribes to document channel
- Edits published to Redis pub/sub
- All connected clients receive edit operations
- Operations applied via Operational Transformation
- Periodic snapshots saved to PostgreSQL
Detailed Design
Component 1: WebSocket Server
Responsibilities:
- Manage WebSocket connections
- Authenticate and authorize clients
- Route messages between clients
- Broadcast presence updates
- Handle reconnection logic
Technology: Node.js with Socket.IO
Key Code:
typescript
// websocket-server.ts
import { Server } from 'socket.io';
import { verifyJWT } from './auth';
import { RedisClient } from './redis';
const io = new Server(server, { cors: { origin: process.env.CLIENT_URL }, transports: ['websocket'], });
io.use(async (socket, next) => { const token = socket.handshake.auth.token; const user = await verifyJWT(token);
if (!user) { return next(new Error('Authentication failed')); }
socket.data.user = user; next(); });
io.on('connection', (socket) => { const { user } = socket.data;
socket.on('join:document', async (docId) => { // Check document permission const canAccess = await checkPermission(user.id, docId); if (!canAccess) { socket.emit('error', { message: 'Unauthorized' }); return; }
// Join document room
socket.join(doc:${docId});
// Broadcast presence
io.to(doc:${docId}).emit('presence:join', {
userId: user.id,
userName: user.name,
cursor: null,
});
// Send current document state const doc = await getDocument(docId); socket.emit('document:state', doc);
// Send current collaborators const collaborators = await getCollaborators(docId); socket.emit('presence:list', collaborators); });
socket.on('edit', async (data) => { const { docId, operation } = data;
// Validate operation if (!validateOperation(operation)) { socket.emit('error', { message: 'Invalid operation' }); return; }
// Publish to Redis for other servers
await redis.publish(doc:${docId}:edits, {
userId: user.id,
operation,
timestamp: Date.now(),
});
// Broadcast to other clients (except sender)
socket.to(doc:${docId}).emit('edit', {
userId: user.id,
operation,
});
// Save to database (async) saveOperation(docId, user.id, operation); });
socket.on('cursor:update', (data) => { const { docId, position, selection } = data;
socket.to(doc:${docId}).emit('cursor:update', {
userId: user.id,
position,
selection,
});
});
socket.on('disconnect', async () => { // Notify others of departure const rooms = Array.from(socket.rooms); rooms.forEach((room) => { if (room.startsWith('doc:')) { socket.to(room).emit('presence:leave', { userId: user.id, }); } }); }); });
Component 2: Operational Transformation Engine
Responsibilities:
- Transform concurrent operations
- Resolve conflicts
- Maintain document consistency
- Ensure convergence
Algorithm: OT (Operational Transformation)
Key Code:
typescript
// ot-engine.ts
interface Operation {
type: 'insert' | 'delete' | 'retain';
position: number;
content?: string;
length?: number;
}
class OTEngine { // Transform operation A against operation B transform(opA: Operation, opB: Operation): Operation { if (opA.type === 'insert' && opB.type === 'insert') { // Both insertions if (opA.position < opB.position) { return opB; // B happens after A } else if (opA.position > opB.position) { // Adjust B's position return { ...opB, position: opB.position + (opA.content?.length || 0), }; } else { // Same position - tie-break by user ID return this.tieBreak(opA, opB); } }
if (opA.type === 'delete' && opB.type === 'insert') { // Delete vs Insert if (opB.position <= opA.position) { return { ...opA, position: opA.position + (opB.content?.length || 0), }; } else if (opB.position > opA.position + (opA.length || 0)) { return opA; } else { // Insert is within delete range return { ...opA, length: (opA.length || 0) + (opB.content?.length || 0), }; } }
// Additional cases... return opA; }
// Apply operation to document apply(doc: string, op: Operation): string { if (op.type === 'insert') { return ( doc.slice(0, op.position) + op.content + doc.slice(op.position) ); }
if (op.type === 'delete') { return ( doc.slice(0, op.position) + doc.slice(op.position + (op.length || 0)) ); }
return doc; }
// Compose two operations compose(op1: Operation, op2: Operation): Operation { // Implementation... return op1; } }
Component 3: Redis Pub/Sub Coordinator
Responsibilities:
- Coordinate between multiple WebSocket servers
- Broadcast operations across servers
- Maintain presence state
Key Code:
typescript
// redis-coordinator.ts
import { createClient } from 'redis';
class RedisCoordinator { private publisher: RedisClient; private subscriber: RedisClient;
async init() { this.publisher = createClient({ url: process.env.REDIS_URL }); this.subscriber = createClient({ url: process.env.REDIS_URL });
await this.publisher.connect(); await this.subscriber.connect();
// Subscribe to edit channels await this.subscriber.pSubscribe('doc::edits', (message, channel) => { const docId = channel.split(':')[1]; const data = JSON.parse(message);
// Broadcast to local clients
io.to(doc:${docId}).emit('edit', data);
});
}
async publishEdit(docId: string, userId: string, operation: Operation) {
await this.publisher.publish(
doc:${docId}:edits,
JSON.stringify({ userId, operation, timestamp: Date.now() })
);
}
async trackPresence(docId: string, userId: string, data: any) {
// Use Redis sorted set for presence with TTL
await this.publisher.zAdd(presence:${docId}, {
score: Date.now(),
value: JSON.stringify({ userId, ...data }),
});
// Set expiration
await this.publisher.expire(presence:${docId}, 3600);
}
async getPresence(docId: string): Promise
// Get active users (within last 5 minutes)
const members = await this.publisher.zRangeByScore(
presence:${docId},
fiveMinutesAgo,
now
);
return members.map((m) => JSON.parse(m)); } }
Data Model
typescript
// Document
interface Document {
id: string;
title: string;
content: string;
version: number;
ownerId: string;
createdAt: Date;
updatedAt: Date;
}
// Operation (edit history) interface DocumentOperation { id: string; documentId: string; userId: string; operation: Operation; version: number; timestamp: Date; }
// Snapshot (periodic full saves) interface DocumentSnapshot { id: string; documentId: string; content: string; version: number; createdAt: Date; }
Database Schema:sql
CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(500) NOT NULL,
content TEXT,
version INTEGER NOT NULL DEFAULT 0,
owner_id UUID NOT NULL REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE document_operations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, user_id UUID NOT NULL REFERENCES users(id), operation JSONB NOT NULL, version INTEGER NOT NULL, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
CREATE INDEX idx_doc_ops_doc_id_version ON document_operations(document_id, version);
CREATE TABLE document_snapshots ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, content TEXT NOT NULL, version INTEGER NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
CREATE INDEX idx_doc_snapshots_doc_id ON document_snapshots(document_id);
Technology Choices
Decision Choice Alternatives Rationale Real-time Protocol WebSocket (Socket.IO) Server-Sent Events, Long Polling Bidirectional, low latency, wide support
Conflict Resolution Operational Transformation CRDT, Last Write Wins Better for text editing, smaller payload
Pub/Sub Redis RabbitMQ, Kafka Simple, fast, existing infrastructure
WebSocket Server Node.js Go, Elixir Team expertise, npm ecosystem
Alternative Approaches
Alternative 1: CRDT (Conflict-free Replicated Data Types)
Description: Use Yjs or Automerge for automatic conflict resolution without transformation.
Pros:
- Simpler conflict resolution logic
- Naturally commutative operations
- Better for rich text
Cons:
- Larger payload sizes (3-5x)
- More memory usage
- Less team expertise
Decision: Not chosen due to payload size concerns and learning curve.
Alternative 2: Server-Side Rendering with Polling
Description: Poll server every 2 seconds for updates, re-render on server.
Pros:
- No WebSocket complexity
- Works with existing infrastructure
- Simple client code
Cons:
- High latency (2s vs 100ms)
- Increased server load
- Poor user experience
Decision: Not chosen due to latency requirements.
Security Considerations
Authentication
- JWT tokens passed via WebSocket handshake
- Tokens expire after 24 hours
- Refresh tokens handled separately
Authorization
- Document access checked on every
join:document event
- Row-level security in PostgreSQL
- Read/write permissions enforced
Data Protection
- WebSocket connections over TLS (wss://)
- At-rest encryption in PostgreSQL
- No sensitive data in Redis pub/sub
Threat Model
Threat 1: Unauthorized document access
- Mitigation: Check permissions on join, verify on every operation
Threat 2: DoS via rapid edits
- Mitigation: Rate limiting (100 ops/min per user), operation size limits
Threat 3: XSS via malicious content
- Mitigation: Content sanitization on render, CSP headers
Threat 4: Connection hijacking
- Mitigation: TLS encryption, token rotation
Performance Considerations
Expected Load
- 10,000 concurrent connections peak
- 5,000 documents being edited simultaneously
- 500 operations per second across all documents
Performance Targets
- Edit Latency: < 100ms p95 (from user A's edit to user B seeing it)
- Connection Time: < 500ms (WebSocket handshake)
- Memory per Connection: < 10MB
- CPU Usage: < 20% for 100 connections
Optimization Strategies
- Connection Pooling: Reuse Redis connections
- Operation Batching: Batch operations sent within 50ms window
- Compression: gzip compress large operations
- Caching: Cache document permissions in Redis (5-minute TTL)
- Snapshots: Create snapshot every 100 operations to avoid replaying all history
Scalability
Horizontal Scaling
- WebSocket servers are stateless (state in Redis)
- Load balancer with sticky sessions (optional)
- Add servers as needed
Capacity Planning
- Current: 2 WebSocket servers (5k connections each)
- 6 months: 4 servers (20k total connections)
- 12 months: 8 servers (40k total connections)
Bottlenecks
- Redis pub/sub throughput: ~100k msgs/sec (sufficient)
- PostgreSQL writes: Batch and async
- Network bandwidth: Monitor and scale
Implementation Plan
Phase 1: Foundation (Week 1-2)
- [x] Set up WebSocket server infrastructure
- [x] Implement authentication
- [x] Create basic pub/sub system
- [ ] Build OT engine core
- [ ] Database schema
Phase 2: Core Features (Week 3-5)
- [ ] Document join/leave functionality
- [ ] Real-time edit propagation
- [ ] Conflict resolution
- [ ] Presence indicators
- [ ] Cursor tracking
Phase 3: Polish & Launch (Week 6-8)
- [ ] Reconnection handling
- [ ] Performance optimization
- [ ] Load testing
- [ ] Security audit
- [ ] Beta launch
- [ ] GA launch
Dependencies
- Blocked by: None
- Blocks: Comment threads feature (depends on real-time infrastructure)
Testing Strategy
Unit Tests
- OT transformation logic (100+ test cases)
- WebSocket event handlers
- Redis coordinator
- Permission checks
Integration Tests
- Full edit flow: Client A edits → Client B receives
- Reconnection scenarios
- Multi-user conflict resolution
- Permission enforcement
Load Tests
- 10,000 concurrent connections
- 500 operations/second sustained
- Connection storm (1000 connections/second)
- Memory leak testing (24-hour soak test)
Security Tests
- Penetration testing by security team
- Rate limiting verification
- Permission bypass attempts
- XSS attack vectors
Monitoring & Observability
Metrics
websocket.connections.active: Current WebSocket connections
websocket.connections.rate: Connections per second
operations.rate: Operations per second
operations.latency: Time from edit to broadcast (p50, p95, p99)
redis.pubsub.latency: Redis pub/sub latency
Logs
json
{
"timestamp": "2024-02-15T10:30:00Z",
"level": "info",
"event": "edit.received",
"userId": "usr_123",
"documentId": "doc_456",
"operation": {"type": "insert", "position": 42, "content": "hello"},
"latency_ms": 45
}
Alerts
- Error rate > 1%: Page engineering
- Edit latency > 500ms p95: Warning
- Connection failures > 5%: Page engineering
- Redis pub/sub lag > 100ms: Warning
Dashboards
- Real-time connection count
- Operations per second
- Edit latency histogram
- Error rate by type
- Active documents count
Rollout Plan
Feature Flags
feature.realtime.enabled: Master toggle
feature.realtime.cursors.enabled: Collaborative cursors
feature.realtime.presence.enabled: Presence indicators
Gradual Rollout
- Internal (Week 6): Engineering and product teams
- Beta (Week 7): 100 invited power users
- 10% (Week 8): 10% of all users
- 50% (Week 9): 50% of all users
- GA (Week 10): 100% of users
Rollback Strategy
- Feature flag disable (instant)
- Fall back to polling mode
- Database rollback scripts prepared
Documentation
User Documentation
- [ ] Real-time collaboration guide
- [ ] Presence indicators explanation
- [ ] Conflict resolution FAQ
- [ ] Troubleshooting guide
Developer Documentation
- [ ] WebSocket API reference
- [ ] OT algorithm documentation
- [ ] Deployment guide
- [ ] Monitoring runbook
Open Questions
- Question: Should we support offline editing with sync on reconnect?
- Impact: High (requires significant additional work)
- Status: Deferred to Phase 2
- Question: What's the maximum document size we support?
- Impact: Medium (affects memory/performance)
- Decision: 1MB limit for Phase 1, revisit later
- Question: Should we implement access control at paragraph level?
- Impact: Low (nice to have)
- Status: Not in scope for v1
Acceptance Criteria
- [x] All functional requirements implemented
- [ ] Edit latency < 100ms p95 in production
- [ ] 99.9% WebSocket uptime
- [ ] Load test: 10k concurrent connections successful
- [ ] Security audit passed
- [ ] Documentation complete
- [ ] Beta feedback: NPS > 8
- [ ] Zero data loss in testing
References
Best Practices for Technical Specifications
1. Start with Why
Always explain:
- What problem are we solving?
- Why does it matter?
- What happens if we don't build this?
2. Define Clear Scope
Include both Goals and Non-Goals:
- ✅ What we're building
- ❌ What we're explicitly NOT building
3. Quantify Success
Use measurable metrics:
- ❌ "Make it faster"
- ✅ "Reduce latency from 500ms to <100ms p95"
4. Consider Alternatives
Document 2-3 alternative approaches:
- Shows you've done your research
- Explains why you chose this path
- Helps future decision-making
5. Include Diagrams
Visual aids help understanding:
- Architecture diagrams (Mermaid)
- Flow charts
- Sequence diagrams
- Entity-relationship diagrams
sequenceDiagram
participant Client A
participant Server
participant Redis
participant Client B
Client A->>Server: Edit operation
Server->>Redis: Publish edit
Redis-->>Server: Broadcast
Server->>Client B: Push edit
Client B->>Client B: Apply operation
6. Address Cross-Cutting Concerns
Always include:
- Security considerations
- Performance targets
- Scalability plans
- Monitoring strategy
7. Plan for Failure
Document:
- What can go wrong?
- How do we detect it?
- How do we recover?
- What's the rollback plan?
8. Make It Reviewable
Structure for async review:
- Clear sections
- Self-contained explanations
- Links to context
- Open questions highlighted
9. Keep It Updated
Treat specs as living documents:
- Update as implementation evolves
- Mark deprecated sections
- Add "Implementation Notes"
- Link to actual code
10. Link Everything
Create a web of knowledge:
- Link to related specs
- Link to ADRs
- Link to implementation code
- Link to documentation
Technical Specification Checklist
Before marking a spec complete:
Content
- [ ] Clear problem statement (why are we building this?)
- [ ] Explicit goals and non-goals
- [ ] Measurable success metrics
- [ ] All functional requirements listed
- [ ] Non-functional requirements defined
- [ ] Proposed solution explained
- [ ] Alternative approaches considered
- [ ] Technology choices justified
Technical Details
- [ ] Architecture diagram included
- [ ] Component responsibilities defined
- [ ] Data model specified
- [ ] API design documented
- [ ] Code examples provided
- [ ] Database schema included
Cross-Cutting Concerns
- [ ] Security considerations addressed
- [ ] Performance targets defined
- [ ] Scalability plan included
- [ ] Monitoring strategy documented
- [ ] Testing strategy outlined
Planning
- [ ] Implementation phases defined
- [ ] Dependencies identified
- [ ] Timeline estimated
- [ ] Rollout plan included
- [ ] Rollback strategy documented
Quality
- [ ] Open questions highlighted
- [ ] Acceptance criteria listed
- [ ] References linked
- [ ] Reviewed by stakeholders
- [ ] Approved for implementation
Organizing Specs in X402
By Feature Area
batch-specs-auth/
├── INDEX.md
├── oauth-implementation.md
├── rbac-system.md
└── session-management.md
batch-specs-api/
├── INDEX.md
├── rest-api-v2.md
├── websocket-api.md
└── graphql-migration.md
By Quarter/Timeline
batch-specs-2024-q1/
├── INDEX.md
├── realtime-collaboration.md
├── advanced-search.md
└── mobile-app.md
With ADRs (Architecture Decision Records)
batch-specs/
├── specs/
│ ├── realtime-collaboration.md
│ └── advanced-search.md
└── adrs/
├── 001-database-choice.md
├── 002-ot-vs-crdt.md
└── 003-websocket-vs-sse.md
Related Questions
How detailed should a tech spec be? Detailed enough that someone unfamiliar with the project can understand the approach and make informed comments. Usually 5-20 pages for major features.
Who should review tech specs? Engineering leads, architects, security team, and affected team members. Aim for 3-5 reviewers.
When should we update specs? Update during implementation when significant decisions change. Add "Implementation Notes" section for learnings.
Should we write specs for small features? Use judgment. Small, straightforward features may only need a brief design doc. Complex features need full specs.
How do specs relate to PRDs (Product Requirements Documents)? PRDs describe WHAT to build (user needs, business goals). Tech specs describe HOW to build it (architecture, implementation).
Quality Standards
- [x] Follows AEO format with Direct Answer
- [x] Includes comprehensive template
- [x] Contains realistic complete example
- [x] Documents best practices
- [x] Provides quality checklist
- [x] Shows organization strategies
- [x] Includes diagrams and code examples
- [x] Ready for production
Start Building with X402
Get our free X402 Implementation Starter Kit with ready-to-use templates, code examples, and best practices.
What is included:
- Quick-start implementation templates
- API integration examples
- Configuration best practices guide