getLocale() }}" dir="rtl"> روافد ديجيتال - لماذا يتوقف المتجر وقت الضغط؟ تشريح 5 أخطاء في السيرفر
السيرفرات وVPS

تشريح حادثة توقف متجر إلكتروني ليلة الجمعة: 5 أخطاء بسيطة في إعداد السيرفر كبّدت المتجر آلاف الدولارات

قصة تقنية بأسلوب Postmortem تشرح كيف اجتمعت RAM غير الكافية وQuery بطيئة وإعداد Workers خاطئ وBackup في وقت الذروة وغياب Monitoring لتوقف متجر أثناء أهم ساعات البيع.

إعداد فريق روافد الرقمية آخر تحديث 2026-08-08

الساعة 7:42 مساءً ليلة الجمعة.

الإعلانات تعمل، الطلبات تدخل، وفريق المتجر يراقب المبيعات ترتفع أسرع من المعتاد.

كان يفترض أن تكون هذه أفضل ليلة في الأسبوع.

بعد أقل من ساعة أصبحت صفحة الدفع تحتاج ثماني ثوانٍ للتحميل.

بعدها بدأت بعض الطلبات تفشل.

ثم ظهرت أول:

502 Bad Gateway

وبحلول الساعة 9 تقريبًا، أصبح جزء كبير من العملاء غير قادر على إكمال الشراء.

المشكلة لم تكن هجومًا، ولم تنقطع الكهرباء عن Datacenter، ولم يتعطل Domain.

المتجر سقط بسبب خمس قرارات صغيرة في إعداد Server كان كل واحد منها يبدو «مقبولًا» عندما كان عدد الزوار منخفضًا.

ملاحظة قبل أن نبدأ

هذه حادثة افتراضية مركبة وليست قصة متجر بعينه. الأرقام والأوقات المستخدمة للتوضيح، لكن الأخطاء التقنية نفسها من المشاكل الشائعة جدًا في متاجر وتطبيقات الإنتاج.

7:42 مساءً — كل شيء يبدو طبيعيًا

المتجر يعمل على VPS بالمواصفات التالية:

4 vCPU
4 GB RAM
80 GB SSD

Ubuntu
Nginx
PHP-FPM
WooCommerce
MariaDB
Redis

في الأيام العادية كان الاستخدام قريبًا من:

RAM:
2.6 - 3.1 GB

CPU:
20% - 45%

ولهذا كان الانطباع:

«السيرفر مرتاحة.»

لكن هذه كانت أول غلطة في طريقة التفكير.

المتجر تم قياسه في يوم عادي، بينما الليلة القادمة لم تكن يومًا عاديًا.

8:03 مساءً — أول شكوى: «الموقع صار ثقيل»

الحملة الإعلانية بدأت تجلب عددًا أكبر من الزوار.

لا يوجد انهيار حتى الآن.

فقط Response Time ترتفع تدريجيًا:

Normal:
350ms

Now:
1.4s

Then:
2.7s

في هذه المرحلة كان يمكن إنقاذ الليلة كلها لو وصلت تنبيه مبكر.

لكن لم يكن هناك Alert.

لا يوجد تنبيه عندما:

Available RAM < 15%

CPU > 85%

Database Connections مرتفعة

Response Time تتجاوز حدًا معينًا

المؤشر الوحيد كان العميل نفسه.

وهنا يظهر الخطأ الأول.

الخطأ الأول: Server اختيرت على Average وليس Peak

وجود 4GB RAM لم يكن المشكلة وحده.

المشكلة أن الاستخدام الطبيعي كان أصلًا:

3GB تقريبًا من أصل 4GB

أي أن المتجر لم يكن يملك Headroom حقيقية.

عند زيادة الزوار زاد عدد PHP Processes، وارتفعت Database Connections، وبدأ Redis يحتفظ ببيانات أكثر.

أصبح الاستهلاك:

OS + services     700 MB
MariaDB          1200 MB
Redis             300 MB
PHP-FPM          2200 MB
Other             250 MB
------------------------
Total            4650 MB

لكن Server لا تملك 4.65GB.

تملك 4GB فقط.

من هنا بدأ الضغط الحقيقي.

المشكلة ليست أن 4GB «سيئة»

4GB قد تكون ممتازة لمتجر آخر.

المشكلة أن هذه Server كانت تحتاج في Peak إلى أكثر من ذلك.

المواصفات يجب أن تبنى على:

Peak المتوقع
+
Headroom

وليس:

متوسط يوم هادئ

8:11 مساءً — RAM وصلت للحد

بدأ النظام باستخدام Swap.

وهذا خفف الانهيار الفوري، لكنه أدخل Server في مشكلة جديدة.

Database التي تحتاج وصولًا سريعًا للذاكرة بدأت تنتظر عمليات تخزين أبطأ.

Response Time ارتفعت أكثر.

والزائر الذي كان يحتاج ثانية للوصول إلى Checkout أصبح ينتظر عدة ثوانٍ.

بعض الزوار ضغطوا Refresh.

وهذا أرسل Requests إضافية إلى Server المتعبة أصلًا.

ما بدأ كنقص بسيط في الموارد أصبح Feedback Loop.

Server بطيئة
    ↓
Users ينتظرون
    ↓
Refresh / Retry
    ↓
Requests أكثر
    ↓
Server أبطأ

8:16 مساءً — Database أصبحت مركز الحادثة

المراقبة اليدوية أظهرت أن MariaDB أصبحت من أكبر مستهلكي CPU.

في البداية كان الاعتقاد:

«نحتاج CPU أكثر.»

لكن Query Log حكت قصة مختلفة.

صفحة داخل المتجر كانت تشغل Query شبيهة بـ:

SELECT ...
FROM order_items
WHERE product_id = ?
ORDER BY created_at DESC;

Table أصبحت كبيرة مع نمو المتجر.

والاستعلام الذي كان سريعًا عندما كانت البيانات قليلة أصبح مكلفًا جدًا بعد أشهر من الطلبات.

المشكلة؟

Index المناسبة غير موجودة.

الخطأ الثاني: Database نمت، لكن تصميم Queries بقي كما كان يوم الإطلاق

عندما كان الجدول يحتوي 10,000 Row لم تكن المشكلة واضحة.

عندما أصبح يحتوي مئات الآلاف من Rows، بدأ الفرق يظهر.

ومع عشرات المستخدمين في الوقت نفسه، أصبحت نفس Query تتكرر باستمرار.

بدل أن تحصل Database بسرعة على Rows المطلوبة، كان عليها فحص كمية أكبر من البيانات.

هنا زيادة CPU يمكن أن تساعد قليلًا، لكنها لا تعالج السبب.

الحل الحقيقي كان مراجعة:

EXPLAIN
Indexes
Slow Query Log
Query frequency
Database schema

وإضافة Index مناسبة بعد اختبارها.

Server أكبر لا تصلح Query سيئة

أحيانًا ترقية CPU تخفي المشكلة لفترة، لكن إذا كان التطبيق يقرأ بيانات بطريقة غير فعالة، سيعود نفس الاختناق عندما ينمو الحمل مرة أخرى.

8:22 مساءً — الفريق يحاول «تسريع» الموقع

ظهر اقتراح سريع:

«زد عدد PHP Workers.»

كان PHP-FPM مضبوطًا على عدد محدود من Workers.

فتم رفع العدد حتى يستطيع الموقع تنفيذ Requests أكثر بالتزامن.

لعدة دقائق بدا أن الحل نجح.

ثم أصبحت Server أسوأ.

الخطأ الثالث: زيادة Workers بدون حساب RAM لكل Worker

إذا كانت PHP Process الواحدة تستهلك مثلًا:

120 MB

فإن:

10 Workers
≈ 1.2 GB

لكن:

25 Workers
≈ 3 GB

وهذا فقط PHP.

ما زالت لديك:

MariaDB
Redis
Nginx
OS
Monitoring
Cron Jobs

رفع `pm.max_children` لم يخلق RAM جديدة.

هو فقط سمح لـPHP باستهلاكها بسرعة أكبر.

بعد دقائق أصبح الضغط على الذاكرة أقوى من قبل.

كيف تحسب Workers بصورة أفضل؟

ابدأ بقياس متوسط وPeak استهلاك Process الحقيقية في تطبيقك.

ثم استخدم ميزانية واضحة:

RAM المسموح بها لـPHP
÷
RAM التقريبية لكل Worker
=
حد مبدئي للـWorkers

ثم اختبر Load فعلية.

لا تنس أن الهدف ليس تشغيل أكبر عدد Workers ممكن.

الهدف هو أعلى Throughput تستطيع Server تحمله بدون انهيار الذاكرة أو Database.

8:34 مساءً — أول 502

بدأ Nginx يعرض:

502 Bad Gateway

بعض PHP Workers توقفت.

ثم ظهرت OOM Events.

Linux أصبح تحت ضغط ذاكرة كافٍ لدرجة أن النظام بدأ يحاول استعادة الذاكرة بالقوة.

إعادة تشغيل PHP-FPM أعادت الموقع مؤقتًا.

لكن السبب لم يختف.

بعد دقائق عادت المشكلة.

8:47 مساءً — جاء أسوأ توقيت ممكن للـBackup

المتجر لديه Backup تلقائية.

وهذا شيء ممتاز.

لكن توقيتها كان:

Friday
8:45 PM

أي أثناء أعلى وقت مبيعات.

بدأت المهمة:

mysqldump
+
ضغط الملفات
+
رفع النسخة إلى Storage خارجي

فجأة أضفنا:

  • قراءة إضافية من Database.
  • CPU للضغط.
  • Disk I/O.
  • Network Traffic.

إلى Server كانت أصلًا على حافة الانهيار.

الخطأ الرابع: مهمة الصيانة تعمل وقت Peak

المشكلة لم تكن وجود Backup.

بل عدم التفكير في وقت تنفيذها وتأثيرها.

هناك Jobs كثيرة تبدو «خفيفة» عندما نراها منفردة:

Backup
Log rotation
Image processing
Reports
Database cleanup
Index maintenance
Scheduled imports

لكن تشغيلها مع Peak Traffic قد يحول Server مستقرة إلى Server مزدحمة.

الحل

قسم Jobs إلى:

Critical
يمكن أن تعمل في أي وقت

Heavy
تعمل خارج Peak

Deferrable
يمكن تأجيلها عند ارتفاع الحمل

وفي البيئات الأكثر أهمية يمكن نقل بعض Jobs إلى Worker منفصلة أو Server مختلفة بدل تنفيذ كل شيء على نفس VPS.

8:52 مساءً — الإدارة تعرف بالمشكلة من العملاء

بدأت رسائل:

«الدفع لا يفتح.»

«الموقع يعلق.»

«خصم المبلغ والصفحة ما كملت.»

هنا اكتشف الفريق مشكلة خامسة.

لم يكن هناك Monitoring خارجي فعلي.

الخطأ الخامس: المراقبة موجودة بعد المشكلة، لا قبلها

معرفة أن Server توقفت بعد اتصال العميل ليست Monitoring.

المراقبة المفيدة يجب أن تجيب قبل الانهيار عن أسئلة مثل:

كم Available RAM الآن؟

هل Swap ترتفع؟

هل Database Connections تقترب من الحد؟

ما P95 Response Time؟

هل Checkout نفسها تعمل؟

هل HTTP 200 ما زالت ترجع؟

هل Disk I/O مرتفعة؟

هل مساحة التخزين تقترب من الامتلاء؟

وكان يجب أن توجد Alerts مثل:

Available RAM < 15% لمدة 5 دقائق

CPU > 85% لمدة 10 دقائق

P95 > 2 seconds

HTTP failures > threshold

Disk > 85%

Database connections > threshold

الأرقام نفسها تختلف حسب التطبيق.

المهم أن يكون هناك إنذار قبل وصول العميل إلى صفحة بيضاء.

9:06 مساءً — وقف النزيف أولًا

في Incident حقيقية، لا تبدأ بإعادة تصميم التطبيق بينما العملاء لا يستطيعون الشراء.

الأولوية الأولى هي Stabilization.

في سيناريو هذه الحادثة كان التدخل المؤقت:

  1. إيقاف Backup الثقيلة.
  2. إعادة PHP Workers إلى رقم آمن.
  3. زيادة RAM مؤقتًا.
  4. إعادة تشغيل الخدمات المتضررة بصورة منظمة.
  5. تقليل الحمل غير الضروري.

عاد المتجر.

لكن هذا لم يكن الحل النهائي.

9:18 مساءً — الموقع عاد، لكن لا نغلق Incident

أحد أخطر الأخطاء بعد عودة الخدمة هو قول:

«خلاص اشتغل.»

عودة الموقع تعني فقط أن مرحلة الطوارئ انتهت.

الآن تبدأ مرحلة معرفة لماذا حدثت المشكلة.

تشريح الأسباب الخمسة

الخطأ ما الذي حدث؟ الإصلاح الدائم
RAM بلا Headroom Peak تجاوزت الذاكرة المتاحة Capacity Planning + هامش نمو
Query بلا Index مناسبة Database CPU ووقت الاستجابة ارتفعا Slow Query Analysis + Indexing
Workers أكثر من قدرة Server PHP استهلكت الذاكرة بسرعة حساب Worker Memory واختبار Load
Backup وقت Peak CPU وDisk وDatabase تحملت عملًا إضافيًا Scheduling أو فصل Jobs الثقيلة
لا توجد Alerts مبكرة العميل اكتشف المشكلة قبل الفريق Monitoring + Thresholds + External Checks

كم كلفت 35 دقيقة من التوقف؟

لنستخدم مثالًا افتراضيًا فقط.

إذا كان المتجر يحقق أثناء الحملة:

120 طلبًا في الساعة

ومتوسط الطلب:
35 ريال

فالإيراد النظري في الساعة:

120 × 35
=
4,200 ريال

إذا تعطلت تجربة الشراء بصورة كبيرة لمدة 35 دقيقة، لا يعني ذلك أن كل هذا المبلغ ضاع حرفيًا.

بعض العملاء سيعودون، وبعض الطلبات ستتم لاحقًا.

لكن الخسارة لا تتكون من المبيعات الفورية فقط.

هناك أيضًا:

  • ميزانية إعلانات استمرت في جلب زوار لا يستطيعون الشراء.
  • طلبات دعم إضافية.
  • Cart Abandonment.
  • عملاء فقدوا الثقة.
  • وقت فريق كامل في Incident.
  • احتمال مشاكل دفع تحتاج مراجعة يدوية.

ولهذا قد تتحول دقائق توقف قليلة أثناء Peak إلى تكلفة كبيرة جدًا.

لكن شراء Server بضعف الحجم ليس الدرس

من السهل قراءة القصة والوصول إلى:

«إذًا نشتري 16GB RAM وتنتهي المشكلة.»

هذا استنتاج ناقص.

لو نقلنا نفس Query السيئة، ونفس Backup، ونفس إعداد Workers، ونفس غياب Monitoring إلى Server أكبر، فنحن غالبًا اشترينا وقتًا فقط.

بعد نمو المتجر ستعود المشكلة.

الحل المستقبلي بدأ من أربعة أسئلة

قبل اختيار Server جديدة، تم حساب:

1. ما Peak RAM الحقيقية؟

2. كم Concurrent Request نحتاج؟

3. ما الموارد التي تحتاجها Database؟

4. ما Headroom التي نحتاجها للحمل والنمو؟

ثم أضيفت خطة تشغيل:

Monitoring
+
Alerts
+
Backup schedule
+
Database maintenance
+
Load testing

هذه هي النقطة التي تتحول فيها الاستضافة من:

«Server عليها موقع»

إلى بنية تستطيع الوثوق بها وقت الضغط.

ما الذي تم تغييره قبل الجمعة التالية؟

لم يكن التغيير واحدًا.

تم بناء قائمة واضحة:

  1. رفع الموارد مع Headroom محسوبة.
  2. مراجعة Slow Queries وإضافة Indexes المطلوبة.
  3. إعادة ضبط PHP-FPM بناءً على استهلاك Worker الفعلي.
  4. نقل Backup إلى فترة أقل ازدحامًا.
  5. إضافة Monitoring وAlerts خارجية.
  6. اختبار Checkout تحت Load قبل الحملة.
  7. توثيق خطوات Incident والاسترجاع.

اختبار الضغط قبل الحملة أرخص من اختباره بالعملاء

إذا كنت تتوقع حملة كبيرة ليلة الجمعة، لا تنتظر ليلة الجمعة حتى تعرف قدرة Server.

قم بتجربة Load مسبقًا في بيئة مناسبة.

لا يكفي اختبار Homepage فقط.

المسار المهم في متجر قد يكون:

Homepage
↓
Category
↓
Product
↓
Add to Cart
↓
Cart
↓
Checkout
↓
Payment initialization

قد تكون Homepage سريعة بفضل Cache بينما Checkout بطيئة بسبب Database.

راقب رحلة العميل، لا Ping فقط

Server قد ترد:

HTTP 200

لكن Checkout تستغرق 12 ثانية.

من الناحية التقنية:

«الموقع شغال.»

من ناحية العميل:

المتجر متوقف تقريبًا.

لهذا راقب أيضًا:

P95 Response Time
Checkout latency
Error rate
Database latency
Queue depth
Payment failures

لو رأيت RAM 95%، لا تقفز فورًا إلى الترقية

اسأل أولًا:

من يستخدمها؟

هل هي Application Memory؟

Database Cache؟

Linux Buffers/Cache؟

Memory Leak؟

عدد Workers؟

Container limit؟

ثم اتخذ القرار بناءً على السبب.

ولو رأيت Database CPU 100%؟

اسأل:

ما Slow Queries؟

هل توجد Full Table Scans؟

هل Indexes مناسبة؟

هل Connections كثيرة؟

هل Queries تتكرر بلا Cache؟

هل التطبيق يرسل نفس Query عدة مرات لكل Page؟

الـMonitoring تخبرك أين الألم.

التحليل يخبرك لماذا.

أفضل Postmortem لا يبحث عن شخص نلومه

السؤال غير المفيد:

«من اختار Server 4GB؟»

السؤال الأفضل:

«لماذا لم يكن لدينا نظام يخبرنا أن 4GB لم تعد تكفي قبل ليلة الحملة؟»

الأنظمة تنمو.

عدد الطلبات يتغير.

Database تكبر.

Plugins تتغير.

ولذلك مواصفات كانت صحيحة قبل ستة أشهر قد لا تكون صحيحة اليوم.

قبل الحملة القادمة

إذا كان متجرك يعتمد على VPS، لا تنتظر Peak لتعرف هل Server مناسبة.

راجع:

Current RAM
Peak RAM
Available RAM
Swap
CPU peak
Load Average
P95 response time
Database slow queries
Workers
Disk I/O
Backup schedule
Monitoring
Alerts

ثم حدد الموارد بناءً على هذه الأرقام.

إذا كنت تخطط لنقل متجر إلى VPS أو تجهيز Server جديدة، فباقات VPS Linux في روافد تتيح لك اختيار الموارد المناسبة لحجم مشروعك، لكن الأهم قبل اختيار الباقة هو معرفة الحمل الذي تحتاج إلى تشغيله فعليًا.

Server الصحيحة ليست التي تحمل أكبر رقم RAM.

هي التي تم اختيارها وتهيئتها ومراقبتها بحيث لا تكون ليلة الجمعة هي أول اختبار حقيقي لها.

لا تجعل وقت الذروة أول اختبار حقيقي لسيرفرك

إذا كنت تجهز متجرًا أو تنقل مشروعًا إلى VPS، احسب Peak والـHeadroom أولًا ثم اختر الموارد المناسبة. يمكنك الاطلاع على باقات VPS Linux في روافد ومقارنة الموارد مع حمل مشروعك الفعلي.

شروحات قد تفيدك أيضًا