← スキル一覧に戻る

versioning-strategy
by AmnadTaowsoam
⭐ 0🍴 0📅 2026年1月24日
SKILL.md
name: Versioning Strategy description: API and system versioning strategies to enable evolution while maintaining backward compatibility.
Versioning Strategy
Overview
Versioning Strategy defines how systems evolve over time while maintaining compatibility with existing clients. Good versioning enables innovation without breaking existing integrations.
Core Principle: "Never break existing clients. Version explicitly, deprecate gracefully."
1. API Versioning Strategies
URL Path Versioning
GET /api/v1/users
GET /api/v2/users
GET /api/v3/users
Pros: Clear, easy to route
Cons: URL pollution, harder to deprecate
Header Versioning
GET /api/users
Header: API-Version: 2024-01-15
Pros: Clean URLs
Cons: Less visible, harder to test in browser
Query Parameter Versioning
GET /api/users?version=2
Pros: Easy to test
Cons: Can be forgotten, mixes with other params
Content Negotiation
GET /api/users
Accept: application/vnd.myapi.v2+json
Pros: RESTful, flexible
Cons: Complex, less discoverable
2. Semantic Versioning (SemVer)
MAJOR.MINOR.PATCH
1.0.0 → 1.0.1 (Patch: Bug fix, backward compatible)
1.0.1 → 1.1.0 (Minor: New feature, backward compatible)
1.1.0 → 2.0.0 (Major: Breaking change)
Examples
1.0.0: Initial release
1.0.1: Fix authentication bug
1.1.0: Add pagination to /users endpoint
1.2.0: Add /products endpoint
2.0.0: Remove deprecated /legacy endpoint
3. Breaking vs Non-Breaking Changes
Non-Breaking (Safe)
// ✅ Adding optional field
interface User {
id: string;
name: string;
email?: string; // New optional field
}
// ✅ Adding new endpoint
GET /api/v1/users/:id/preferences // New endpoint
// ✅ Adding new query parameter (optional)
GET /api/v1/users?sort=name // New optional param
Breaking (Dangerous)
// ❌ Removing field
interface User {
id: string;
// name: string; // REMOVED - breaks clients expecting this
}
// ❌ Changing field type
interface User {
id: number; // Was string, now number - BREAKING
}
// ❌ Renaming endpoint
GET /api/v1/accounts // Was /users - BREAKING
// ❌ Making optional field required
interface User {
email: string; // Was optional, now required - BREAKING
}
4. Versioning in Code
Version Routing (Express)
import express from 'express';
const app = express();
// V1 routes
app.get('/api/v1/users', v1.getUsers);
app.get('/api/v1/users/:id', v1.getUser);
// V2 routes (with new features)
app.get('/api/v2/users', v2.getUsers); // Includes pagination
app.get('/api/v2/users/:id', v2.getUser); // Includes preferences
Shared Logic
// Shared business logic
class UserService {
async getUser(id: string): Promise<User> {
return await db.users.findById(id);
}
}
// V1 controller
class V1UserController {
async getUser(req, res) {
const user = await userService.getUser(req.params.id);
res.json({ id: user.id, name: user.name }); // V1 response format
}
}
// V2 controller
class V2UserController {
async getUser(req, res) {
const user = await userService.getUser(req.params.id);
res.json({
id: user.id,
name: user.name,
email: user.email, // V2 includes email
preferences: user.preferences // V2 includes preferences
});
}
}
5. Database Schema Versioning
Expand-Contract Pattern
-- Phase 1: Expand (add new column)
ALTER TABLE users ADD COLUMN email_address VARCHAR(255);
-- Dual writes (write to both old and new)
UPDATE users SET email = ?, email_address = ? WHERE id = ?;
-- Phase 2: Migrate data
UPDATE users SET email_address = email WHERE email_address IS NULL;
-- Phase 3: Contract (remove old column)
ALTER TABLE users DROP COLUMN email;
Migration Scripts
// migrations/001_add_email.ts
export async function up(db: Database) {
await db.schema.alterTable('users', (table) => {
table.string('email_address');
});
}
export async function down(db: Database) {
await db.schema.alterTable('users', (table) => {
table.dropColumn('email_address');
});
}
6. Deprecation Strategy
Deprecation Timeline
## Deprecation Timeline for /api/v1/users
- **2024-01-15**: Announce deprecation (6 months notice)
- **2024-04-15**: Add deprecation headers
- **2024-07-15**: Remove from documentation
- **2024-07-15**: Sunset endpoint (stop accepting new clients)
Deprecation Headers
app.get('/api/v1/users', (req, res) => {
res.set('Deprecation', 'true');
res.set('Sunset', 'Sat, 15 Jul 2024 00:00:00 GMT');
res.set('Link', '</api/v2/users>; rel="successor-version"');
// Return data
res.json(users);
});
7. Client SDK Versioning
// SDK v1
import { UserClient } from '@myapi/sdk';
const client = new UserClient({ version: 'v1' });
const user = await client.getUser('123');
// SDK v2
import { UserClient } from '@myapi/sdk';
const client = new UserClient({ version: 'v2' });
const user = await client.getUser('123'); // Returns more fields
8. Versioning Checklist
- Strategy Chosen: URL path, header, or content negotiation?
- SemVer Adopted: Using semantic versioning?
- Breaking Changes Identified: Clear what breaks compatibility?
- Deprecation Policy: Timeline for sunsetting old versions?
- Documentation: All versions documented?
- Monitoring: Track usage of each version?
- Migration Guide: Help clients upgrade?
- Backward Compatibility: Maintain for at least 6 months?
Related Skills
59-architecture-decision/deprecation-policy51-contracts-governance/api-contracts45-developer-experience/release-workflow
スコア
総合スコア
60/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です