ساعت ۱۰:۰۲، تیم محصول سقف درخواست یک API را کم میکند. سلامت سرورها سبز است و بیشتر پاسخها هم ۲۰۰ هستند؛ اما اپلیکیشن یکی از شرکا پس از چند پاسخ ۴۲۹، همه درخواستها را همزمان تکرار میکند. صف سفارش بالا میرود، توکنهای قدیمی هنوز معتبرند و هیچکس نمیداند کدام مشتری روی نسخه قبلی مانده است. این رخداد فقط «مشکل Rate Limit» نیست؛ شکست در مدیریت قرارداد مصرفکننده API است.
API خوب صرفاً Endpoint سالم ندارد. باید از لحظه ثبت یک مصرفکننده تا صدور Credential، اعمال مجوز، سهمیهبندی، تکامل قرارداد، مهاجرت و در نهایت بازنشستگی نسخه قابل اداره باشد. در این راهنما Rate Limiting، Authentication و Versioning را نه سه قابلیت جدا، بلکه اجزای یک چرخه عمر واحد میبینیم. اگر ابتدا به نمای کلی نیاز دارید، راهنمای طراحی API امن، قابل اتکا و قراردادمحور نقطه شروع مکملی است.
مسئله واقعی: چه قراردادی با مصرفکننده بستهاید؟
مصرفکننده ممکن است اپ موبایل خودتان، یک سرویس داخلی، فروشنده بازارگاه، شرکت لجستیک، درگاه پرداخت یا نرمافزار حسابداری مشتری باشد. هرکدام مالک، الگوی ترافیک، سطح دسترسی و سرعت انتشار متفاوتی دارند. بنابراین «API عمومی» یا «API داخلی» برای تصمیمگیری کافی نیست؛ باید قرارداد عملیاتی هر گروه روشن باشد.
| لایه قرارداد | پرسش عملی | شاهد قابل بررسی |
|---|---|---|
| هویت | چه کاربر یا سامانهای درخواست میدهد؟ | Client registry، شناسه Credential و مالک |
| مجوز | این هویت روی کدام منبع چه عملی انجام میدهد؟ | Scope، Role، Policy و تست منفی |
| داده | فیلدها، نوعها، Null و Enum چه معنایی دارند؟ | OpenAPI، مثال و Contract test |
| رفتار | ترتیب، Side effect، Idempotency و خطا چیست؟ | سناریوی پذیرش و Error catalog |
| قابلیت اتکا | Timeout، Retry و سطح خدمت چگونه است؟ | SLI/SLO و Runbook |
| ظرفیت | سهمیه بر چه واحد و کلیدی محاسبه میشود؟ | Rate policy و داشبورد مصرف |
| چرخه عمر | تغییر، اعلام، مهاجرت و پایان پشتیبانی چگونه است؟ | نسخه، Deprecation plan و فهرست Clientها |
هر پاسخ مبهم در این جدول، بدهی عملیاتی است. مثلاً اگر Scope مستند باشد اما هیچ تستی دسترسی یک فروشنده به سفارش فروشنده دیگر را رد نکند، قرارداد مجوز فقط روی کاغذ وجود دارد. برای Threat model، BOLA/IDOR و الگوهای دفاعی، مقاله امنیت API با OWASP، OAuth و JWT عمق بیشتری دارد.
پیش از کدنویسی، فهرست مصرفکنندگان را بسازید
تیمی که نمیداند چه کسی API را مصرف میکند، نمیتواند Credential را بچرخاند یا نسخهای را بازنشسته کند. یک Client registry حداقل باید این موارد را نگه دارد:
- شناسه Client، سازمان/تیم مالک، فرد پاسخگو و راه ارتباط اضطراری؛
- محیطهای Development، Sandbox و Production و Credential مستقل هر محیط؛
- Scopeها، مسیرهای مجاز، نسخه یا Capabilityهای مصرفی و SDK مورد استفاده؛
- حجم معمول و پیک، سفر بحرانی مثل پرداخت یا ثبت بارنامه و SLO مرتبط؛
- رده داده، کشور/محدودیت قراردادی، آخرین زمان مشاهده و تاریخ انقضا؛
- سیاست Rate Limit، استثناها و دلیل و تاریخ بازبینی هر استثنا.
ثبت دستی اولیه اشکالی ندارد، اما وضعیت «آخرین مصرف» و نسخه باید از Telemetry بیاید. Clientی که شش ماه دیده نشده شاید حذفشدنی باشد؛ شاید هم فرایند فصلی مالیاتی است. حذف بدون تماس یا شاهد، حدس پرهزینهای است.
Rate Limiting یعنی تخصیص ظرفیت، نه سپر جادویی DDoS
Rate Limit برای عدالت میان مستأجرها، کنترل هزینه، حفاظت از وابستگیهای کند، اجرای پلن تجاری و جلوگیری از اشباع ظرفیت مفید است. اما بهتنهایی حمله DDoS را خنثی نمیکند. حتی تولید پاسخ ۴۲۹، بررسی Credential و مراجعه به Store توزیعشده میتواند زیر حمله منابع مصرف کند. کنترل لبه شبکه، CDN/WAF، محدودیت اتصال، تشخیص الگوی سوءاستفاده و امکان Drop کردن درخواست هنوز لازماند؛ راهنمای مقابله با باتهای پیشرفته و سوءاستفاده خودکار این مرز را دقیقتر پوشش میدهد.
سیاست Rate را پیش از الگوریتم تعریف کنید
پرسش اول «Token Bucket یا Sliding Window؟» نیست. ابتدا سیاست را با ورودیهای زیر بنویسید:
| تصمیم | نمونه | ریسک بیتصمیمی |
|---|---|---|
| واحد | درخواست، بایت، عملیات همزمان یا Cost point | برابری ظاهری میان عملیات ارزان و گران |
| Partition key | Tenant + Client + Route | مصرف یک مشتری، دیگران را متوقف میکند |
| پنجره و Burst | ۱۲۰ درخواست در دقیقه با Burst بیستتایی | رد شدن Burst مشروع یا آزاد شدن جهش مخرب |
| سلسلهمراتب | سقف Route، Tenant و Global | دور زدن سقف با پخش ترافیک میان مسیرها |
| پاسخ | ۴۲۹، Retry-After و Problem Details | Retry کور و طوفان درخواست |
| حالت خرابی | Fail-open محدود یا Fail-closed برای عملیات حساس | تصمیم تصادفی هنگام قطع Store |
کلید محدودسازی را ترجیحاً بعد از احراز هویت بسازید. IP برای ترافیک ناشناس یک سیگنال است، نه هویت قطعی: صدها کاربر اپراتور موبایل، دانشگاه یا شرکت ممکن است پشت NAT مشترک باشند و یک کاربر هم با VPN چند IP داشته باشد. برای Endpoint لاگین میتوان ترکیبی از IP، حساب، Device signal و الگوی رفتاری داشت؛ اما سیاست باید False positive و مسیر بازیابی را هم بسنجد.
الگوریتم باید با شکل بار هماهنگ باشد
- Token Bucket: نرخ میانگین را نگه میدارد و Burst کنترلشده میپذیرد؛ برای API تعاملی انتخاب رایجی است.
- Fixed Window: ساده است، اما در مرز دو پنجره میتواند جهش دوبرابری بسازد.
- Sliding Window یا GCRA: توزیع زمانی منصفانهتری میدهد، با پیچیدگی و هزینه بیشتر.
- Concurrency limit: برای گزارش سنگین، آپلود یا وابستگی کند، تعداد عملیات همزمان را مهار میکند.
- Cost-weighted limit: به جستوجوی ساده یک امتیاز و به Export بزرگ دهها امتیاز میدهد.
در سامانه چندنمونهای، دقت Counter، تأخیر شبکه و دسترسپذیری Store با هم مبادله میشوند. اگر همه درخواستها برای یک Counter مرکزی قفل شوند، خود Limiter گلوگاه میشود؛ اگر Counterها محلی باشند، سقف تقریبی است. این انتخاب را با بودجه خطا و اثر تجاری مستند کنید، نه با عبارت مبهم «Distributed Rate Limiting».
پاسخ ۴۲۹ باید Client را به رفتار درست هدایت کند
RFC ۶۵۸۵ وضعیت 429 Too Many Requests را برای عبور از نرخ مجاز تعریف میکند و اجازه میدهد پاسخ شامل Retry-After باشد. خود RFC نمیگوید هویت یا شمارش دقیقاً چگونه تعیین شود؛ این بخش سیاست سرویس شماست. بدنه خطا باید Machine-readable، دارای شناسه رخداد و فاقد جزئیات حساس باشد.
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 8
{
"type": "https://api.example.ir/problems/quota-exceeded",
"title": "سهمیه موقت این عملیات پر شده است",
"status": 429,
"retry_after_seconds": 8,
"trace_id": "01J..."
}Headerهای قدیمی X-RateLimit-Limit، X-RateLimit-Remaining و X-RateLimit-Reset در عمل دیده میشوند، اما نباید آنها را استاندارد رسمی معرفی کرد. در تاریخ این بازبینی، پیشنویس فعال IETF با نام RateLimit Fields یک Internet-Draft در حال کار است و فیلدهای RateLimit-Policy و RateLimit را پیشنهاد میکند؛ پیشنویس ممکن است تغییر کند. اگر Header عمومی میدهید، معنای نسخه فعلی آن را بخشی از قرارداد و مستندات Client بدانید.
قانون Retry برای Client
Retry-Afterرا رعایت کند؛ در نبود آن از Exponential backoff با Full jitter استفاده کند.- تعداد تلاش و زمان کل را محدود کند و Deadline کسبوکار را بشناسد.
- فقط عملیات Idempotent را خودکار تکرار کند؛ برای POST مالی، Idempotency key لازم است.
- با Circuit breaker و Queue محلی از کوبیدن وابستگی بیمار جلوگیری کند.
- Retry را در Metric جدا ببیند تا پاسخ موفق پس از پنج تلاش، خطای پنهان تلقی نشود.
Jitter حیاتی است: اگر هزار Client دقیقاً هشت ثانیه بعد برگردند، یک موج همزمان تازه میسازند. در مسیرهایی مانند ثبت سفارش، Call timeout و وضعیت نامعلوم را نیز طراحی کنید؛ «پاسخ نگرفتیم» معادل «عملیات انجام نشد» نیست.
Authentication و Authorization را عمداً جدا کنید
Authentication میپرسد «این درخواست از طرف چه هویتی است؟» و Authorization میپرسد «این هویت اجازه انجام این عمل روی این منبع را دارد؟». توکن معتبر دلیل کافی برای دسترسی به هر Order ID نیست. مجوز باید در هر درخواست، در سطح Object و Action و با Context روز بررسی شود. چکلیست سختسازی و تست امنیت Endpointهای API برای آزمونهای منفی این بخش کاربردی است.
| روش | کاربرد مناسب | خط قرمز |
|---|---|---|
| API Key | شناسایی Client یا پروژه و سهمیهبندی | جایگزین هویت کاربر نهایی یا Authorization نیست |
| OAuth 2.0 | واگذاری دسترسی محدود به Client | بهتنهایی پروتکل Login/هویت فدره نیست |
| OpenID Connect | لایه هویت روی OAuth ۲.۰ | ID Token نباید کورکورانه برای هر API پذیرفته شود |
| mTLS/Workload identity | هویت سرویسبهسرویس با سطح اطمینان بالا | چرخه Certificate و مالکیت باید مدیریت شود |
| Basic over TLS | سناریوی محدود و کنترلشده Legacy | Credential انسانی بلندمدت و بدون Rotation مناسب نیست |
API Key را مثل Secret حامل مدیریت کنید
کلید را در Header بفرستید، نه Query string یا کد JavaScript مرورگر؛ URL در Log، History و Referrer نشت میکند. مقدار کامل را فقط هنگام صدور نشان دهید، در Store بهصورت امن نگه دارید، Prefix غیرحساس برای تشخیص داشته باشید و Scope، انقضا، Rotation و Revocation را پشتیبانی کنید. برای هر شریک و هر محیط کلید مستقل بدهید تا رخداد یک Client به خاموش کردن همه منجر نشود.
OAuth، OIDC و JWT سه مفهوم یکسان نیستند
OAuth ۲.۰ چارچوب واگذاری مجوز است. «ورود با ارائهدهنده هویت» معمولاً به OpenID Connect و کنترلهای هویتی آن نیاز دارد. RFC ۹۷۰۰ که در ژانویه ۲۰۲۵ منتشر شده، بهترین رویههای امنیتی جاری OAuth ۲.۰ را گردآوری میکند: Authorization Code همراه PKCE، اعتبارسنجی دقیق Redirect URI، محدود کردن Audience و سطح دسترسی، و حفاظت از Tokenهای دسترسی و Refresh.
JWT فقط یک قالب فشرده برای Claimهاست؛ امضا بهتنهایی محتوا را «درست، تازه یا مجاز» نمیکند. Resource server باید الگوریتم مجاز را Allowlist کند، امضا و کلید را بررسی کند و Claimهایی مثل iss، aud، exp، nbf و نوع Token را مطابق قرارداد اعتبارسنجی کند. چرخه تعویض کلید، Cache شدن JWKS، لغو دسترسی و مقابله با Replay نیز باید تصمیم صریح داشته باشد.
چرخه عمر Credential را از روز اول طراحی کنید
Credential بدون مالک و تاریخ پایان، حساب مشترک دائمی میسازد. چرخه کامل چنین است:
ثبت Client → تأیید مالک و Scope → صدور → تحویل امن → استفاده و پایش
→ Rotation → Revoke/Expire → پاسخ به رخداد → ثبت و بازبینی- صدور: کمترین Scope، Audience مشخص، محیط مستقل و Expiry متناسب با ریسک.
- تحویل: Secret manager یا کانال یکبارمصرف؛ هرگز تیکت عمومی و پیام گروهی.
- Rotation: دوره همپوشانی دو کلید، مشاهده مهاجرت و سپس قطع کلید قبلی.
- Revocation: عملیات فوری، شناسه Credential و اثر Clientهای وابسته روشن باشد.
- رخداد: Leak را با Log بدون خود Secret، Scope مصرفشده و Timeline قابل پیگیری کنید.
برای Machine-to-machine، Credential ثابت چندساله را عادی نکنید. هویت Workload و Token کوتاهعمر در بسیاری از معماریها Blast radius را کم میکند؛ بااینحال راهکار باید با زیرساخت واقعی و امکان بازیابی تیم شما تناسب داشته باشد.
قبل از ساخت v2، تکامل سازگار را امتحان کنید
نسخه جدید همیشه پاسخ نخست نیست. تغییر Additive و سازگار معمولاً هزینه کمتری دارد: افزودن فیلد اختیاری، افزودن Endpoint تازه یا افزودن Capability با Negotiation. این روش فقط وقتی امن است که Client فیلد ناشناخته را تحمل کند، به ترتیب JSON متکی نباشد و Enum جدید را به Crash تبدیل نکند.
| نوع تغییر | نمونه | احتمال شکست |
|---|---|---|
| Schema | حذف/تغییر نام فیلد، تغییر String به Number | بالا و آشکار |
| Enum و Null | افزودن وضعیت تازه، Nullable شدن فیلد | بالا در Clientهای سختگیر |
| معنا | تغییر تعریف «موجودی قابل فروش» | بالا اما گاهی بیصدا |
| امنیت | Scope تازه یا سختگیری Audience | قطع دسترسی Client قدیمی |
| ظرفیت | کاهش Quota یا تغییر Cost عملیات | ۴۲۹ و Retry storm |
| رفتار | تغییر ترتیب، Pagination، Side effect یا Error code | ناسازگاری منطقی |
| زمان | Timeout کوتاهتر یا Consistency متفاوت | خطاهای متناوب |
Breaking change فقط حذف یک فیلد نیست. تغییر مجوز، Quota، semantics یا زمانبندی هم میتواند قرارداد را بشکند. این موارد را در Review تغییرات و Release gate کنار Diff فایل OpenAPI بررسی کنید.
روش Versioning را بر اساس کانال مصرف انتخاب کنید
نسخه در مسیر مانند /v1/orders برای مشاهده و Route کردن ساده است. نسخه در Header، URI تمیزتری میدهد اما Debug و Cache را پیچیدهتر میکند. نسخه تاریخی برای APIهایی با Snapshot زمانی مشخص مناسب است. هیچ محل واحدی همیشه بهترین نیست؛ ثبات قرارداد و ابزار مهاجرت مهمتر از سلیقه URL است.
- Major version را برای شکستن قرارداد نگه دارید؛
v1معمولاً ازv1.0روشنتر است. - نسخه و Capability را در Log و Metric ثبت کنید، وگرنه میزان مهاجرت قابل سنجش نیست.
- OpenAPI، SDK، مثال، Sandbox و پیادهسازی باید از یک Release pipeline عبور کنند.
- در GraphQL معمولاً Deprecation فیلد و تکامل Schema مهمتر از نسخه مسیر است؛ مقایسه GraphQL و REST برای انتخاب معماری API تفاوتها را باز میکند.
یک نسخه برای همه Endpointها همیشه ضروری نیست. ولی Versioning ریز و نامنسجم هم ماتریس پشتیبانی را انفجاری میکند. مرز را حول یک Domain و قرارداد منسجم تعیین کنید و سیاست پشتیبانی را قبل از انتشار نسخه بنویسید.
Deprecation یک پروژه مهاجرت است، نه یک ایمیل
RFC ۹۷۴۵ در مارس ۲۰۲۵ Header استاندارد Deprecation و Link مربوط به مستندات Deprecation را تعریف کرد. میتوان آن را با Sunset همراه کرد؛ زمان Sunset نباید پیش از شروع Deprecation باشد. Header مفید است، اما Clientی که پاسخ را نمیبیند یا مالک فعالی ندارد با Header مهاجرت نمیکند.
- کشف: Clientهای فعال، مسیرها، نسخه، حجم، سفر بحرانی و مالک را از Telemetry استخراج کنید.
- طراحی: Mapping قبل/بعد، تغییر رفتار، Errorها، Scopeها و Quota را در Migration guide بنویسید.
- آمادهسازی: Sandbox، SDK، نمونه کد، Contract test و ابزار مقایسه پاسخ بدهید.
- اعلام: Header، داشبورد، ایمیل هدفمند و تماس مستقیم برای Clientهای حیاتی را ترکیب کنید.
- همزیستی: دو نسخه را موقت اجرا و درصد ترافیک و خطای هر Cohort را رصد کنید.
- Escalation: نزدیک Sunset، مالکهای مهاجرتنکرده و استثناهای زماندار را به تصمیمگیر برسانید.
- خاموشی: معیار Go/No-Go، Rollback محدود و پیام خطای قابل اقدام داشته باشید.
Deprecation: @1767225600
Sunset: Wed, 01 Jul 2026 00:00:00 GMT
Link: <https://developer.example.ir/migrations/v2>; rel="deprecation"عدد ثابت مثل «همه نسخهها پس از ۱۸۰ روز حذف شوند» قانون عمومی نیست. دوره مناسب به قرارداد، ریسک، تعداد Client، چرخه انتشار اپ موبایل و اهمیت مسیر بستگی دارد. موعد باید واقعبینانه باشد اما بیپایان هم نماند؛ هر تمدید مالک، دلیل و تاریخ پایان داشته باشد.
Contract test باید رفتار مصرفکننده را پوشش دهد
Diff فایل OpenAPI تغییرات Schema را میبیند، ولی تغییر معنای قیمت، ترتیب پردازش یا Policy مجوز را لزوماً نمیبیند. سه لایه تست لازم است:
- Provider contract: پاسخ، Error، Header، Validation و Compatibility با Specification.
- Consumer contract: فرضهای Clientهای واقعی؛ از جمله Enum ناشناخته، فیلد اختیاری و Timeout.
- Runtime conformance: مقایسه ترافیک واقعی با قرارداد برای یافتن Drift مستندات و پیادهسازی.
برای هر Endpoint حساس، تست منفی مجوز، تست Retry و Idempotency، رفتار ۴۲۹، انقضای Token و کلید قدیمی را هم اجرا کنید. در سامانه رویدادمحور، Backpressure و تحویل تکراری به قرارداد بیرونی وصلاند؛ راهنمای معماری Event-Driven با Outbox و Saga مرز Async را تکمیل میکند.
Rollout را بر اساس Cohort مصرفکننده انجام دهید
انتشار API با Deploy کد تمام نمیشود. Clientها مستقل از شما منتشر میشوند و بعضی نسخه اپ موبایل ماهها در بازار میماند. Rollout امن میتواند این مراحل را داشته باشد:
- ترافیک ضبطشده یا Synthetic را روی نسخه تازه Replay کنید و داده حساس را حذف کنید.
- Shadow traffic را بدون Side effect اجرا و اختلاف پاسخ را اندازه بگیرید.
- یک Client داخلی یا شریک داوطلب را Canary کنید.
- درصد را بر اساس Client ID، نه صرفاً درصد تصادفی درخواست، افزایش دهید.
- Error، Latency، ۴۰۱/۴۰۳/۴۲۹، Retry و KPI کسبوکار را کنار هم ببینید.
- Rollback قرارداد را تعریف کنید؛ بازگشت کد وقتی داده مهاجرت کرده همیشه کافی نیست.
داشبورد باید نسخه و Client cohort را ببیند، ولی Cardinality مهارنشده نسازد. برای طراحی Metric، Log، Trace، SLO و Alert به راهنمای Observability و مانیتورینگ لحظهای مراجعه کنید.
تعامل Rate، Auth و Version را جداگانه تست نکنید
بیشتر رخدادها در تقاطع کنترلها رخ میدهند:
- نسخه جدید Scope تازه میخواهد؛ Client توکن قدیمی میفرستد و ۴۰۳ میگیرد.
- مهاجرت Client باعث Sync اولیه و Burst میشود؛ Quota قدیمی آن را ۴۲۹ میکند.
- Rotation کلید با Cache احراز هویت همزمان نیست و بخشی از Nodeها کلید جدید را رد میکنند.
- Endpoint جدید هزینه بیشتری دارد، اما Limiter همه درخواستها را یک واحد حساب میکند.
- Client پس از ۴۰۱ توکن را Refresh میکند و پس از ۴۲۹ Retry؛ ترکیب خطاها Loop میسازد.
ماتریس تست Release باید نسخه × Credential state × Quota state × نوع Client را پوشش دهد. همه ترکیبها لازم نیستند؛ Risk-based انتخاب کنید، اما سناریوهای بحرانی پرداخت، ثبت سفارش و لغو را کنار Happy path تست کنید.
سناریوهای ایران: قرارداد محلی را صریح کنید
یک فروشگاه ایرانی معمولاً به PSP، پیامک، ERP، لجستیک و بازارگاه متصل است؛ برخی وابستگیها شبکه ناپایدار، پنل محدود یا SLA متفاوت دارند. در این محیط چند تصمیم را به حدس Client واگذار نکنید:
- پول: IRR یا تومان، Minor unit، گردکردن و منبع مبلغ نهایی را مستند کنید. نام فیلد
amountبدون واحد کافی نیست. - شماره تماس: قالب
+98یا09، نرمالسازی و رفتار شماره نامعتبر روشن باشد. - زمان: Timestamp را با Offset/UTC ذخیره کنید و نمایش تهران را جدا بدانید؛ تعطیلی یا تغییرات تقویمی نباید در Contract پنهان باشد.
- پرداخت: Callback تکراری، وضعیت نامعلوم و Verify باید Idempotent باشد؛ راهنمای یکپارچهسازی درگاه پرداخت جریان مالی را دقیقتر بررسی میکند.
- شبکه و Provider: Timeout، Retry budget، Circuit breaker و مسیر جایگزین را برای اختلال ISP یا سرویسدهنده تمرین کنید.
- پشتیبانی: مستند فارسی روشن مفید است، اما نام فیلد، Error code و مثال باید میان نسخه فارسی و انگلیسی همسان بماند.
نمونه: سرویس پیامک در پاسخ اولیه Timeout میدهد، ولی پیام را فرستاده است. Retry بدون Idempotency یا شناسه کسبوکار، پیام تکراری و هزینه اضافه میسازد. Rate Limit هم نباید صف Retry را ناگهان آزاد کند؛ Worker باید Jitter و سقف همزمانی داشته باشد.
Runbookهای ضروری برای تیم On-call
| رخداد | تشخیص نخست | اقدام مهار |
|---|---|---|
| جهش ۴۲۹ | Client/Route/Version، Retry ratio و Saturation وابستگی | مهار Retry storm، Quota موقت زماندار یا کاهش بار |
| نشت Key/Token | شناسه Credential، Scope، IP/Client و Timeline | Revoke/Rotate، محدود کردن Scope و حفظ شواهد |
| پاسخ ناسازگار | Deploy، Schema diff و Client cohort | Flag/rollback، توقف Rollout و اطلاع هدفمند |
| Client جامانده از Sunset | آخرین مصرف، مالک و سفر بحرانی | استثنای کوتاه و محدود یا برنامه Cutover همراه |
| قطع Store محدودسازی | سلامت Store و اختلاف Counterها | اجرای حالت Fail-open/closed از پیش تصویبشده |
| اختلال Identity Provider | Token issuance در برابر validation محلی | حفظ Token معتبر، مهار Refresh storm و اطلاعرسانی |
Runbook باید Query آماده، مالک تصمیم، محدودیت اقدام، متن ارتباطی و شرط بازگشت داشته باشد. «بررسی Logها» اقدام نیست؛ مشخص کنید کدام داشبورد، کدام فیلتر و چه آستانهای تصمیم را عوض میکند.
نقشه اجرای ۳۰، ۶۰ و ۹۰روزه
روز ۱ تا ۳۰: دیدپذیری و مالکیت
- Client registry و مالک صد Client/Service پرترافیک را کامل کنید.
- نسخه، Credential ID غیرحساس، Route، Status و Latency را در Telemetry ثبت کنید.
- Endpointهای مالی و تغییردهنده وضعیت را برای Idempotency، Scope و Retry ممیزی کنید.
- سیاست فعلی Quota و استثناهای بدون تاریخ را استخراج کنید.
روز ۳۱ تا ۶۰: قرارداد و کنترل
- Rate policy را بر اساس Tenant/Client/Route و Cost بازطراحی و در Sandbox آزمون کنید.
- چرخه Rotation/Revoke و سناریوی نشت Credential را تمرین کنید.
- Contract diff و Consumer test را به CI اضافه کنید.
- راهنمای سازگاری برای Null، Enum، Pagination، Error و Deprecation منتشر کنید.
روز ۶۱ تا ۹۰: مهاجرت تمرینی
- یک تغییر واقعی اما محدود را با Shadow، Canary و Cohort rollout عبور دهید.
- Header و داشبورد Deprecation را روی یک نسخه کمریسک آزمایش کنید.
- Runbookهای ۴۲۹، نشت کلید، IdP outage و Contract regression را Game day کنید.
- نتیجه را با زمان کشف، زمان مهار، خطای Client و KPI کسبوکار مرور کنید.
چکلیست Release یک تغییر API
- مالک Domain و مصرفکنندگان تحتتأثیر مشخصاند.
- تغییر Schema، معنا، Authorization، Quota، Error و Timing بررسی شده است.
- OpenAPI، SDK، مثال، Sandbox و کد Runtime همنسخهاند.
- Contract test مثبت و منفی و سناریوی Retry/Idempotency پاس شدهاند.
- Metricهای Client، Version، ۴۰۱، ۴۰۳، ۴۲۹، Latency و KPI تعریف شدهاند.
- Canary cohort، آستانه توقف و Rollback داده/کد روشناند.
- اگر Breaking است، Migration guide، Deprecation، Sunset و تماس مالکها آمادهاند.
- تغییر Credential یا Rate با Version جدید بهصورت ترکیبی تست شده است.
معیار بلوغ این نیست که «API ما JWT و v2 دارد». معیار این است که تیم بتواند نشان دهد چه کسی چه دسترسی دارد، چرا یک درخواست محدود شده، کدام Client از تغییر میشکند، مهاجرت چگونه سنجیده میشود و هنگام رخداد چه تصمیمی در چند دقیقه نخست گرفته خواهد شد.
پرسشهای متداول
آیا Rate Limiting جلوی حمله DDoS را میگیرد؟
بهتنهایی خیر. Rate Limit برای تخصیص ظرفیت و مهار سوءاستفاده مفید است، اما بررسی و تولید ۴۲۹ هم منابع مصرف میکند. دفاع لایه شبکه و Edge، WAF/CDN، محدودیت اتصال، تشخیص رفتار و Runbook حمله همچنان لازماند.
تفاوت Authentication و Authorization چیست؟
Authentication هویت درخواستکننده را اثبات میکند؛ Authorization اجازه همان هویت برای انجام یک عمل روی منبع مشخص را میسنجد. توکن معتبر بدون بررسی مالکیت Object و Scope، دسترسی امن ایجاد نمیکند.
آیا JWT ذاتاً امن و Stateless است؟
خیر. JWT قالب Token است. امنیت به الگوریتم و کلید مجاز، اعتبارسنجی Issuer/Audience/Expiry، انتقال امن، طول عمر و کنترل Replay وابسته است. لغو، Rotation و وضعیت حساب هم ممکن است State یا مراجعه به سامانه دیگری بخواهد.
بهترین روش Versioning API چیست؟
پاسخ واحدی وجود ندارد. ابتدا تکامل سازگار را امتحان کنید؛ اگر Breaking change ضروری است، مسیر، Header یا نسخه تاریخی را متناسب با Client، Cache و عملیات انتخاب کنید. ثبات روش، Telemetry مصرف و برنامه مهاجرت از محل شماره نسخه مهمترند.
چه زمانی نسخه قدیمی را خاموش کنیم؟
پس از شناسایی Clientهای فعال، ارائه مسیر مهاجرت و Sandbox، مشاهده کاهش مصرف نسخه قدیمی و تأیید معیارهای Go/No-Go. تاریخ باید از ریسک و قرارداد بیاید، نه یک عدد عمومی؛ استثناها نیز باید محدود، مالکدار و زماندار باشند.
منابع فنی این بازبینی
- RFC ۶۵۸۵: وضعیت ۴۲۹ و Retry-After
- IETF Internet-Draft: RateLimit Fields for HTTP؛ سند در حال کار در زمان بازبینی
- RFC ۹۷۰۰: بهترین رویههای امنیت OAuth ۲.۰
- RFC ۸۷۲۵: بهترین رویههای امنیت JWT
- RFC 9745: Deprecation Header
جمعبندی: Rate Limit، Authentication و Versioning زمانی ارزش دارند که در یک سیستم مالکیت و شواهد قرار بگیرند: Client registry، Credential lifecycle، قرارداد قابل تست، Telemetry نسخه، مهاجرت مرحلهای و Runbook. با این پیوند، تغییر API از یک Deploy پرریسک به فرایندی قابل مشاهده، قابل توقف و قابل بازگشت تبدیل میشود.






