AWS وسّعت Durable Functions: إمتى تستبدل الـ queue المخصص؟
لو عندك workflow بتقع في نصها وتحتاج تكمل من آخر خطوة، توسع AWS Lambda Durable Functions يوم 22 أبريل 2026 يفتح اختيار عملي جديد: تكتب orchestration أقل، لكن تقبل ارتباط أقوى ببيئة Lambda.
مستوى القارئ: متوسط
المشكلة باختصار
الطريقة الشائعة في فرق كتير إنك تبني state table في DynamoDB، وتحط retry worker، وتضيف queue بين كل خطوة وخطوة. الطريقة دي بتشتغل، لكنها بتفشل تدريجيًا لما الـ workflow يبقى فيه انتظار طويل أو callback من خدمة خارجية.
مثال واضح: عندك onboarding لشركة جديدة. الخطوات هي إنشاء tenant، شحن بطاقة، انتظار موافقة مسؤول، إرسال بريد، ثم تفعيل الحساب. لو الخطوة الثالثة أخدت 6 ساعات، Lambda العادية لا ينفع تفضل نايمة. ولو كتبت sleep داخل الكود فأنت بتدفع compute بلا قيمة.
AWS أعلنت في 22 أبريل 2026 إن Lambda Durable Functions أصبحت متاحة في 16 منطقة إضافية، منها London وParis وZurich وTel Aviv وSão Paulo وUS West N. California. الخبر مهم لأنه يقرب نفس النمط من المستخدم والبيانات، بدل ما تبقى مربوط بمنطقة واحدة بعيدة.
الفكرة ببساطة قبل التعريف الرسمي
ركز في المثال ده: بدل ما تكتب عامل منفصل يتابع هل الدفع تم أم لا، بتكتب دالة واحدة فيها خطوات. خطوة تدفع. خطوة تنتظر webhook. خطوة ترسل الإيميل. لو التنفيذ وقع بعد الدفع، النظام لا يعيد الدفع من جديد. هو يعيد تشغيل الدالة ويستخدم نتيجة الخطوة المكتملة من checkpoint.
التعريف الدقيق: Durable Functions تضيف primitives داخل handler مثل steps وwaits. الـ step يحفظ تقدم العملية، والـ wait يوقف التنفيذ ثم يستأنفه لاحقًا. حسب وثائق AWS، الـ wait لا يستهلك زمن تنفيذ Lambda أثناء التوقف في on-demand functions، والحد الأعلى للانتظار يمكن أن يصل إلى سنة في نمط الانتظار.
اللي بيحصل فعلاً إن الدالة قد تُستدعى أكثر من مرة. عند الاستئناف، Lambda تعيد تشغيل الكود من البداية، لكنها تتخطى الخطوات المكتملة وتعيد نتائجها من سجل الـ checkpoint. لهذا السبب لازم يكون الكود deterministic. يعني لا تعتمد على Date.now() أو random داخل قرار مهم إلا لو حفظت النتيجة كجزء من step.
مثال تنفيذي: order workflow صغير
الافتراض إن عندك خدمة طلبات أقل من 20 ألف طلب يوميًا، وكل طلب يحتاج دفع ثم انتظار webhook ثم إرسال بريد. هذا مثال Node.js توضيحي قريب من نمط durable handler. أسماء الحزم قد تختلف حسب SDK النهائي في مشروعك، لكن الفكرة التنفيذية هي ترتيب الخطوات وفصل التأثيرات الجانبية داخل steps مسماة.
export const handler = async (event, context) => {
const durable = context.durable;
const order = await durable.step("load-order", async () => {
return await getOrder(event.orderId);
});
const charge = await durable.step("charge-card", async () => {
return await stripe.paymentIntents.create({
amount: order.amountCents,
currency: "usd",
customer: order.customerId
});
});
await durable.waitForCallback("payment-webhook", {
timeoutSeconds: 60 * 60 * 24
});
await durable.step("send-confirmation", async () => {
return await sendEmail(order.email, charge.id);
});
return { ok: true, orderId: order.id };
};المكسب هنا إن retry بعد سقوط مؤقت لا يشحن العميل مرتين طالما خطوة الدفع محفوظة صح. الخسارة إنك لازم تفهم replay كويس. أي side effect خارج step ممكن يتكرر.
قبل وبعد بأرقام معقولة
في implementation مخصص، غالبًا تملك 5 أجزاء تشغيلية: Lambda أولى، queue، جدول حالة، retry worker، وmonitoring خاص. مع Durable Functions ممكن تقللها إلى دالة durable، checkpoints، ومراقبة من Lambda console. الرقم هنا تقديري لكنه واقعي لفريق صغير.
لو فريقك يقضي ساعتين أسبوعيًا في متابعة retry jobs العالقة، تقليل الأجزاء من 5 إلى 2 قد يوفر 4 إلى 6 ساعات شهريًا. المقابل إن تكلفة Lambda لا تختفي. ستظل تدفع على invocations، وعلى compute وقت التنفيذ الفعلي، وقد تظهر تكلفة replay أو تخزين checkpoint حسب نمط الاستخدام والتسعير الحالي.
القرار العملي: تستخدمها فين؟
- استخدمها عندما يكون الـ workflow من 3 إلى 8 خطوات، وكل خطوة لها نتيجة واضحة يمكن حفظها.
- استخدمها عندما يوجد انتظار طويل: موافقة بشرية، webhook دفع، polling محدود، أو مهمة AI تنتظر مراجعة.
- استخدمها عندما تريد إبقاء الفريق داخل Lambda بدل إدارة Step Functions وworkers وجداول حالة مخصصة.
- لا تنقل كل شيء مرة واحدة. ابدأ بـ workflow واحد فيه ألم حقيقي في retry أو انتظار.
الـ trade-off هنا واضح: بتكسب كود orchestration أقل وتجربة أقرب للمطور. بتخسر استقلالية التصميم، لأن المنطق يصبح مربوطًا أكثر بنموذج Lambda والـ durable SDK.
متى لا تستخدم هذه الطريقة
لا تستخدمها لو الـ workflow عندك يحتاج رسم بصري واضح، approvals كثيرة من فرق مختلفة، أو branching معقد جدًا؛ Step Functions قد تكون أوضح. لا تستخدمها لو عندك workload عالي جدًا يحتاج queue backpressure مستقل. ولا تستخدمها لو كل خطوة قصيرة جدًا وتنتهي في أقل من ثانية؛ وقتها Lambda عادية أو queue بسيط قد يكون أرخص وأسهل.
كذلك لا تستخدمها لو الكود غير deterministic. مثال: لو خطوة تعتمد على random discount ثم ترسل فاتورة، لازم تحفظ الخصم داخل step. غير كده replay ممكن يعطي نتيجة مختلفة، وده أسوأ من الفشل العادي.
مصادر وتحقق
- إعلان AWS بتاريخ 22 أبريل 2026 عن التوسع إلى 16 منطقة إضافية.
- دليل AWS Lambda Durable Functions.
- شرح AWS لفكرة replay وتخطي الخطوات المكتملة.
- صفحة تسعير AWS Lambda وتفاصيل waits في durable functions.
الخطوة التالية
اختار workflow واحد عندك فيه انتظار خارجي أو retry مؤلم. ارسم خطواته في 10 دقائق، وحدد أي خطوة لها side effect. لو لقيت أكثر من 3 side effects قابلة للحفظ، جرّب prototype صغير بـ Durable Functions قبل ما تبني queue مخصص جديد.