أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

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

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

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول
How To Make It

اعمل Feature Flags داخلي بـ Unleash وNode.js

📅 ٢٦ أبريل ٢٠٢٦⏱ 4 دقائق قراءة
اعمل Feature Flags داخلي بـ Unleash وNode.js

اعمل Feature Flags داخلي بـ Unleash وNode.js

مستوى القارئ: متوسط

هتطلع من المقال ده بنظام Feature Flags بسيط يخليك تطلق ميزة على 5% من المستخدمين، تراقبها، ثم تزودها بدون deploy جديد.

المشكلة باختصار

الطريقة الشائعة إنك تعمل deploy وتعتبر إن الميزة اتنشرت لكل الناس. الطريقة دي بتفشل لما يظهر bug بعد أول ساعة. بدل ما توقف السيرفر أو ترجع commit، الأفضل تخلي الكود موجود، لكن تشغيله متحكم فيه من لوحة خارجية.

افترض إن عندك API عليها 50 ألف مستخدم يوميًا. لو نشرت صفحة checkout جديدة لكل المستخدمين مرة واحدة، فأي bug في الدفع ممكن يضرب 100% من الطلبات. مع Feature Flag تبدأ بـ 5% فقط. لو عندك 10 آلاف زيارة للـ checkout في اليوم، فأنت بتعرّض حوالي 500 زيارة في البداية بدل 10 آلاف.

مخطط يوضح تطبيق Node.js يسأل Unleash قبل تفعيل ميزة تدريجيًا للمستخدمين

الفكرة بمثال بسيط

ركز في المثال ده. عندك زر جديد اسمه new_checkout. بدل ما تكتب شرطًا ثابتًا داخل الكود، التطبيق يسأل Unleash: هل المستخدم الحالي يشوف الزر الجديد؟ لو الإجابة نعم تعرض المسار الجديد. لو لا، تترك المسار القديم يعمل.

المفهوم العلمي وراء ذلك بسيط: Feature Flag هو قرار runtime. الكود موجود في الإنتاج، لكن تفعيله لا يحتاج بناء نسخة جديدة. Unleash يخزن القواعد والاستراتيجيات، وSDK في Node.js يقيّم القرار محليًا بناءً على context مثل userId أو sessionId. هذا مهم لأن الـ stickiness يحافظ على نفس القرار لنفس المستخدم، بدل ما يشوف الميزة مرة وتختفي مرة.

الخطوات العملية

  1. شغّل Unleash محليًا للتجربة.
  2. أنشئ feature flag باسم new_checkout.
  3. اربط تطبيق Node.js بالـ API token.
  4. ابدأ rollout بنسبة 5%، ثم ارفعها إلى 25% وبعدها 100%.
  5. راقب الأخطاء والزمن قبل كل زيادة.
YAML
# docker-compose.yml
services:
  postgres:
    image: postgres:15
    environment:
      POSTGRES_DB: unleash
      POSTGRES_USER: unleash_user
      POSTGRES_PASSWORD: unleash_pass
    volumes:
      - pgdata:/var/lib/postgresql/data

  unleash:
    image: unleashorg/unleash-server:latest
    ports:
      - "4242:4242"
    environment:
      DATABASE_HOST: postgres
      DATABASE_NAME: unleash
      DATABASE_USERNAME: unleash_user
      DATABASE_PASSWORD: unleash_pass
      DATABASE_SSL: "false"
      INIT_FRONTEND_API_TOKENS: default:development.unleash-insecure-frontend-api-token
      INIT_CLIENT_API_TOKENS: default:development.unleash-insecure-api-token
    depends_on:
      - postgres

volumes:
  pgdata:
Bash
docker compose up -d
# افتح http://localhost:4242
# أنشئ flag باسم new_checkout ثم فعّله في development
npm init -y
npm i express unleash-client
JavaScript
// server.js
const express = require('express');
const { initialize } = require('unleash-client');

const unleash = initialize({
  url: 'http://localhost:4242/api/',
  appName: 'checkout-api',
  customHeaders: {
    Authorization: 'default:development.unleash-insecure-api-token'
  }
});

const app = express();

app.get('/checkout', (req, res) => {
  const userId = req.query.userId || 'anonymous';
  const enabled = unleash.isEnabled('new_checkout', { userId });

  if (enabled) {
    return res.json({ flow: 'new_checkout', discountBox: true });
  }

  return res.json({ flow: 'classic_checkout', discountBox: false });
});

app.listen(3000, () => console.log('API on http://localhost:3000'));
Bash
node server.js
curl "http://localhost:3000/checkout?userId=42"

النتيجة المتوقعة: نفس userId يفضل على نفس القرار طالما إعدادات الـ rollout ثابتة. ده بالظبط اللي يمنع تجربة متذبذبة للمستخدم.

القياس قبل وبعد

بدون Feature Flag، أول deploy يعرض 100% من المستخدمين للكود الجديد. مع rollout بنسبة 5%، أنت تقلل مساحة الخطر 20 مرة في أول مرحلة. الرقم ليس ضمانًا ضد الأخطاء، لكنه يحدد حجم الضرر لو ظهر bug.

رسم أعمدة يوضح تقليل تعريض المستخدمين من 100% إلى 5% عند استخدام feature flags

راقب 3 أرقام قبل رفع النسبة: معدل أخطاء 5xx، زمن P95 للـ endpoint، وعدد عمليات checkout الناجحة. مثال عملي: لو P95 زاد من 220ms إلى 480ms عند 5%، لا ترفع النسبة. أصلح السبب أو اقفل الفلاج فورًا.

الـ trade-off هنا

المكسب: تفصل deploy عن release، وتقدر تعمل kill switch في ثواني. التكلفة: هتضيف اعتمادًا جديدًا على Unleash، وهتحتاج تنظيف الفلاجز القديمة. لو تركت 30 flag منسية في الكود، هتدفع تكلفة فهم وصيانة في كل تعديل.

أفضل طريقة إنك تكتب owner وتاريخ انتهاء لكل flag. Flag خاص بإطلاق ميزة يجب أن يُحذف بعد الاستقرار. Flag خاص بإطفاء خدمة خارجية ممكن يفضل لأنه operational kill switch.

متى لا تستخدم هذه الطريقة

لا تستخدم Feature Flags لكل if statement صغيرة. لو التغيير داخلي ولا يؤثر على المستخدم، الـ deploy العادي كفاية. لا تستخدمها أيضًا لإخفاء migration غير متوافقة مع قاعدة البيانات. لو schema الجديد يكسر القديم، أنت محتاج خطة migration، مش مجرد flag.

مصادر اعتمدت عليها

  • Unleash Feature Toggles
  • Unleash Gradual Rollout
  • Unleash Node.js SDK
  • Docker Compose documentation
  • OpenFeature introduction

الخطوة التالية

الخطوة التالية: اختار ميزة واحدة عندك فيها خطر واضح، واعمل لها flag باسم محدد، وابدأ rollout بنسبة 5% فقط لمدة يوم قبل أي زيادة.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة