ستّة أسابيع. هذه كانت المهلة الكاملة بين اليوم الذي استُدعينا فيه وصباح الجمعة الذي ستوجّه فيه حملة وطنية ما يقارب عشرين ضعف حركة المرور المعتادة نحو منصّة تلهث أصلاً في أيّ يوم صرف رواتب عادي. كانت المساحات الإعلانية محجوزة، والميزانية مصروفة، وتاريخ الإطلاق مثبّتاً في عقدٍ لا يقبل التأجيل. الشيء الوحيد الذي ظلّ قابلاً للتغيير هو البنية المعمارية تحت السطح — وذلك فقط إن تحرّكنا بحذرٍ وسرعة معاً.
طرح علينا العميل سؤالاً واحداً صريحاً: هل ستصمد؟ يوم دخلنا كانت الإجابة الأمينة: لا. من هنا تقلّص التكليف من الطموح إلى الفرز — أن نقرّر ما الذي نقوّيه، وما الذي نؤجّله، وما الذي نحميه مهما كان الثمن.
الموقف
كان العميل منصّة استهلاكية متوسطة الحجم في منطقة الخليج — بضعة ملايين من المستخدمين المسجّلين، وعلامة إقليمية معروفة، وفريق هندسي صغير لكنه كفؤ، بنى المنتج جيّداً للحمل الذي يتعامل معه، لا للحمل القادم. كان النظام تطبيقاً واحداً يستند إلى قاعدة بيانات أساسية واحدة، تجري عليها مسارات الدفع والحسابات بشكلٍ متزامن (synchronous). في يومٍ عادي كان هذا كافياً تماماً. لكنّ الحملة لن توزّع الطلب على أسبوع، بل ستضغطه في ساعاتٍ قليلة خلال عطلة نهاية أسبوعٍ واحدة؛ والتركيز، لا الحجم، هو ما يكسر الأنظمة.
التحدّي
كل قيدٍ حقيقي كان يشير إلى الاتجاه نفسه. لا وقت لإعادة كتابة النظام ولا رغبة في ذلك. التاريخ لا يتزحزح. والفريق صغير بما يكفي ليعني أنّ أيّ شيء نُدخِله يجب أن يكون قابلاً للتشغيل من قِبل من هم على المناوبة فعلاً، لا من قِبل كتيبة خبراء نرحل ونتركها خلفنا. كما لم يكن مقبولاً أن نُضعِف تجربة العملاء الذين يستخدمون المنتج يومياً. لم يُطلب منّا بناء المنصّة التي ستحتاجها الشركة بعد ثلاث سنوات، بل أن ننجح في عطلة نهاية أسبوعٍ واحدة دون أن نُفسد الواحدة والخمسين التي تليها.
منهجنا
تعاملنا مع الإطلاق بوصفه مسألة سعة (capacity) ذات موعدٍ نهائي صارم، وعالجناه بترتيبٍ مقصود بدل إصلاح ما يبدو الأكثر إلحاحاً في اللحظة.
- القياس قبل لمس أيّ شيء. بنينا منظومة load test تعيد تشغيل حركة مرور واقعية وتضغط حتى الانهيار، لنعرف السقف الحقيقي للمنصّة — لا الرقم المعروض على اللوحة — وأيّ مكوّن ينهار أولاً.
- حماية مسار المال. رسمنا خطاً صارماً حول الدفع وإتمام الشراء، واعتبرنا كلّ ما عداه قابلاً للتفاوض تحت الضغط.
- التصميم للتدهور الرشيق (graceful degradation). لم يكن الهدف خدمة كلّ طلبٍ بكامل غناه، بل إبقاء القلب يعمل بينما تتنحّى الميزات غير الأساسية بهدوء.
- التمرين على اليوم نفسه، لا على الشيفرة فقط. كان دليل التشغيل (run-book) ويوم المحاكاة الحيّ (game-day) بأهمية أيّ تغيير تقني منفرد.
ما الذي فعلناه
بعد رسم السقف، صارت التدخّلات دقيقة الهدف لا شاملة. وضعنا طبقة cache أمام مسارات القراءة الثقيلة، ونقلنا الأصول الثابتة والوسائط إلى CDN، وهو ما أزاح وحده حصّة كبيرة من الحمل عن الأصل (origin). أضفنا read replicas حتى تتوقّف حركة التصفّح والتقارير عن مزاحمة عمليات الكتابة. أبقينا كتابات الدفع متزامنة، أمّا كلّ ما عداها تقريباً — الإشعارات، التحليلات، تحديثات الولاء — فنقلناه خلف queue لتُعالَج بُعيد لحظة الذروة. لفّينا النداءات الهشّة نحو الخدمات الخلفية بـ circuit breakers، ووضعنا feature flags على الأجزاء غير الأساسية من التجربة، لنتمكّن من تخفيف الحمل في ثوانٍ بدل نشر شيفرة تحت النار. وجعلنا الطبقة عديمة الحالة (stateless) تتوسّع آلياً (autoscaling). ثم تمرّنّا: يوم محاكاة كامل على حملٍ شبيه بالإنتاج، والفريق كله يراقب اللوحات نفسها التي سيراقبها صباح الإطلاق.
النتيجة
| المؤشر | قبل | بعد |
|---|---|---|
| ذروة الحركة المُستوعَبة دون فشل | ينهار قرب 2–3 أضعاف المعتاد | صمد عبر نحو 20 ضعف المعتاد |
| زمن الاستجابة p95 عند الذروة | عدّة ثوانٍ | أقل من ثانية |
| معدّل الأخطاء أثناء الضغط | أرقام من خانتين | أقل من 1% بوضوح |
| نجاح إتمام الشراء تحت الحمل | غير موثوق (~70%) | فوق 99% |
| التعافي بعد موجة ضغط | يدوي، ساعات | آلي، دقائق |
مرّت عطلة الحملة كيومٍ مزدحمٍ عادي لا كحادثة. وصلت الحركة قريباً مما توقّعه التسويق، فاستوعبتها المنصّة، وبقيت قناة المناوبة هادئة بما يكفي ليقضي الفريق ليلته يراقب الرسوم البيانية بدل إطفاء الحرائق. والأهمّ أنّ شيئاً مما أضفناه لم يُضعِف التجربة اليومية في الأسابيع التي سبقت أو تلت.
ما الذي صنع الفارق
ثلاثة أمورٍ رجَحت على ما عداها. أولاً، قِسنا قبل أن نبني؛ فقد أخبرنا الـ load test أنّ عنق الزجاجة الحقيقي هو قاعدة البيانات، لا طبقة التطبيق حيث كانت غريزة الفريق تشير، وهذا وفّر أسابيع. ثانياً، تفوّق التدهور الرشيق على السعة بالقوة الغاشمة؛ فالقدرة على تنحية الميزات غير الأساسية عبر feature flag كانت أرخص وأكثر موثوقية من توفير عتادٍ لذروةٍ نأمل أن نُحسن تخمينها. ثالثاً، كان التمرين هو المُنتَج؛ إذ كشف يوم المحاكاة نمطَي فشلٍ كنّا سنواجههما مباشرةً على الهواء، وحوّل فريقاً متوتراً إلى فريقٍ هادئ.
البنية التي تركناها ليست الشكل النهائي للمنصّة — لكنها بنية تستطيع الآن أن تلاقي موجتها القادمة بوصفها حدثاً مخطَّطاً له، لا مقامرة.