المستوى: متوسط — هذا المقال يفترض أنك تعرف ما هو HTTP Cache-Control وعملت إعداد reverse proxy من قبل (NGINX أو CDN). لو لسه مبتدئ في الـ caching، اقرأ مقال HTTP Cache-Control الأساسي قبل ده.
endpoint بيرد في 240ms علشان بيعمل JOIN على 3 جداول كل request. لو ضيفت سطر واحد في الـ Cache-Control بيرد في 12ms على 95% من الطلبات، بدون أن البيانات تبقى قديمة لأكثر من دقيقة واحدة. المسؤول عن السحر ده توجيه اسمه stale-while-revalidate من RFC 5861.
Stale-While-Revalidate: استجابة فورية وتحديث في الخلفية
المشكلة باختصار
لو الـ API بتاعك بيرجع home feed أو list of products، الناس بتطلبه آلاف المرات في الدقيقة. كل طلب بيمشي على نفس الـ DB query، نفس الـ aggregation، ونفس الـ serialization. 99% من النتايج هتكون مكرّرة.
الحل المعتاد: cache عادي بـ Cache-Control: max-age=60. هنا بتقع في فخ تاني. ساعة انتهاء الكاش، أول طلب يجي بيلاقي cache miss، يستنى الـ origin يرد كامل، والمستخدم يدفع 240ms cold latency. ده اللي بيتسمى cache stampede أو thundering herd لو أكثر من طلب جه في نفس اللحظة.
مثال للمبتدئ: محل العصير في الصبح
تخيّل محل عصير بيعمل عصير برتقال طازج. عصرة دورق واحد بتاخد 4 دقائق. لو كل زبون يدخل المحل والبائع يبدأ يعصر له من الأول، طابور هيتكوّن في ثواني وكل واحد هيستنى دقايق.
اللي بيعمله البائع الذكي: بيعصر دورق كبير الصبح ويحطه على الـ counter. أي زبون يجي ياخد كوباية في 5 ثواني من الدورق الجاهز. لما الدورق يقرب يخلص، البائع يبدأ يعصر دورق جديد في الخلفية، والزباين يفضلوا يأخذوا من القديم لحد ما الجديد يبقى جاهز.
ده بالظبط Stale-While-Revalidate. الكاش بيرد بسرعة من النسخة القديمة، وفي نفس الوقت بيبعت request للـ origin يجيب نسخة جديدة في الخلفية. ولا زبون استنى. ولا origin اتحمّل أكتر من اللازم.
التعريف العلمي الدقيق
توجيه stale-while-revalidate موجود في RFC 5861 منذ 2010. الصياغة الكاملة:
Cache-Control: max-age=60, stale-while-revalidate=600اللي بيقوله الـ header ده للـ cache (متصفح أو CDN أو reverse proxy):
- اعتبر النسخة دي طازجة لمدة 60 ثانية. خلال الفترة دي، رد منها فوراً بدون أي اتصال بالـ origin.
- بعد الـ 60 ثانية، النسخة بقت stale (قديمة). لو طلب جديد جا، رد عليه من النسخة القديمة دي مباشرة، وفي الخلفية ابعت طلب async للـ origin علشان تجيب نسخة جديدة.
- الكاش يقدر يقدّم نسخة قديمة لمدة أقصاها 600 ثانية إضافية بعد انتهاء max-age.
- بعد 660 ثانية كاملة، أي طلب لازم ينتظر الـ origin (cache miss عادي).
القيمتين مش عشوائيتين. = الفترة اللي مقبول فيها أن البيانات تبقى طازجة 100%. = الفترة الإضافية اللي مقبول فيها بيانات قديمة كحد أقصى.