انتقل إلى المحتوى الرئيسي
  • عمرو سمير
    • الرئيسية
    • المدونة
    • المشاريع
    • من أنا
    • المهارات
    • الخبرات
    • تواصل
    • شهادات
  • عمرو سمير
    • صمم بواسطةعمرو سمير
    • كل الحقوق محفوظة (2026)

    • github
    • twitter
التخزين المؤقت وتحسين الأداء في أنظمة الإنتاج

التخزين المؤقت وتحسين الأداء في أنظمة الإنتاج

دليل عملي من منظور Full-Stack Developer حول استخدام caching و Redis و CDN والمراقبة وتحسين الأداء لبناء أنظمة إنتاج أسرع وأكثر استقرارًا.

11 دقيقة • تطوير الواجهة الخلفية • ٣٠ أبريل ٢٠٢٦

هذا المقال عن

نست جي إسنست جي إسنود جي إسنود جي إسجينجينهندسة الباك إندهندسة الباك إندجافاسكربتجافاسكربتتايب سكريبتتايب سكريبتجو / جولانججو / جولانجأمن التطبيقاتأمن التطبيقات#Production Systems#Scalability#Database Optimization#CDN#Redis#Performance#Caching#Go#NestJS#Node.js#Backend

التخزين المؤقت وتحسين الأداء في أنظمة الإنتاج

خوادم وبنية تحتية

مرحبًا، اسمي Amr Samir، وأنا Full-Stack Web Developer، وفي هذا المقال أريد أن أتكلم عن موضوع يبدو بسيطًا من الخارج، لكنه يصنع فرقًا كبيرًا جدًا في أنظمة الإنتاج: Caching و Performance.

ربما نعم، التخزين المؤقت يبدو كفكرة سهلة. نخزن البيانات مؤقتًا، ونرجعها بسرعة في الطلبات التالية، وانتهى الأمر. لكن ربما لا — لأن الـ caching في الإنتاج ليس مجرد طريقة لتسريع الاستجابة فقط. هو أيضًا وسيلة لتقليل الضغط على قاعدة البيانات، حماية الـ backend من الزيادات المفاجئة في الترافيك، تحسين تجربة المستخدم، والحفاظ على استقرار النظام مع نمو المنتج.

النظام السريع ليس مجرد ميزة لطيفة. هو جزء من الاعتمادية.

عندما يفتح المستخدم صفحة، أو يستدعي API، أو يحدث dashboard، هو لا يهتم بمدى تعقيد الـ backend. هو يهتم أن كل شيء يفتح بسرعة ويعمل بشكل مستقر. كمطورين، دورنا أن نجعل هذا يحدث بدون أن نضغط على قاعدة البيانات في كل طلب.

وهنا يأتي دور caching وتحسين الأداء.


لماذا يعتبر Caching مهمًا؟

الـ caching يعني تخزين البيانات المستخدمة بكثرة في مكان أسرع من المصدر الأصلي.

بدلًا من سؤال قاعدة البيانات نفس السؤال مرة بعد مرة، نخزن الإجابة في طبقة أسرع مثل الذاكرة، Redis، Memcached، CDN، أو حتى browser cache.

مثلًا، تخيل endpoint مثل:

GET /api/products/featured

إذا كان آلاف المستخدمين يطلبون نفس المنتجات المميزة كل دقيقة، فليس من المنطقي أن نضرب قاعدة البيانات في كل مرة. غالبًا هذه البيانات لا تتغير كل ثانية. يمكننا تخزينها لفترة قصيرة وإرجاع أغلب الطلبات من الـ cache.

هذا يعطينا ثلاث فوائد مهمة:

  1. استجابة أسرع.
  2. ضغط أقل على قاعدة البيانات.
  3. قابلية توسع أفضل.

وبصراحة، هذا من أكثر التحسينات العملية التي يمكن إضافتها لأنظمة الـ backend. أنت لا تغير المنتج بالكامل، ولا تعيد كتابة النظام من الصفر. أنت فقط تجعل العمل المتكرر أقل تكلفة.


الفكرة الأساسية

الطلب العادي بدون caching قد يكون بهذا الشكل:

نفس الفكرة يمكن توضيحها بشكل بسيط ومتوافق مع Markdown العادي:

Client -> API Server -> Database -> API Server -> Client

الـ API يستقبل الطلب، يقرأ البيانات من قاعدة البيانات، ثم يرجع الرد إلى العميل.

مع caching، الطلب يصبح أذكى:

Client -> API Server -> Cache Check
                     |-> Cache HIT  -> Return Cached Data -> Client
                     |-> Cache MISS -> Query Database -> Save Result in Cache -> Client

أول طلب قد يكون أبطأ لأنه يحتاج إلى قراءة البيانات من قاعدة البيانات. لكن بعد ذلك، الطلبات المتكررة يتم إرجاعها بسرعة من الـ cache.

وهذه هي الفكرة الأساسية: لا تنفذ عملًا مكلفًا إذا كانت النتيجة موجودة بالفعل.


In-Memory Cache أم Distributed Cache؟

هناك طريقتان شائعتان للتفكير في caching داخل تطبيقات الـ backend.

1. In-memory cache

هذا النوع يعيش داخل نفس process الخاصة بالتطبيق.

مثلًا، في Node.js يمكن استخدام JavaScript object أو LRU cache في الذاكرة. وفي Go يمكن استخدام map أو package مخصصة للـ caching.

الميزة أنه سريع جدًا لأنه لا يوجد network call. التطبيق يقرأ مباشرة من الذاكرة.

لكن المشكلة أن كل instance من التطبيق لها cache منفصل.

إذا كان لديك خمس backend servers خلف load balancer، فكل واحدة منها تمتلك cache مختلفة. قد تكون البيانات موجودة في instance وغير موجودة في أخرى. وهذا يؤدي إلى cache misses وسلوك غير ثابت أحيانًا.

الـ in-memory cache مناسب للبيانات الصغيرة، المحلية، المؤقتة، أو البسيطة. لكنه ليس دائمًا الخيار الأفضل للبيانات المشتركة في الإنتاج.

2. Distributed cache

الـ distributed cache يكون مشتركًا بين أكثر من application instance.

من أشهر الأمثلة:

  • Redis
  • Memcached
  • KeyDB
  • Managed cache services في خدمات cloud

هذا الأسلوب أفضل في الإنتاج لأن كل backend instances تستطيع القراءة من نفس طبقة الـ cache.

الـ distributed cache يجعل طبقة التخزين المؤقت مشتركة بين كل backend instances:

Client -> Load Balancer
          |-> API Instance 1 -> Redis Cache -> Database
          |-> API Instance 2 -> Redis Cache -> Database
          |-> API Instance 3 -> Redis Cache -> Database

كل application instances تستطيع القراءة من نفس الـ cache، وهذا يجعل النظام أكثر استقرارًا من أن يكون لكل server cache منفصل.

لكن المقابل هو زيادة التعقيد. Redis يصبح خدمة إضافية تحتاج إلى تشغيل، تأمين، مراقبة، scaling، وخطة recovery. ومع ذلك، في الأنظمة الجادة، هذا التعقيد غالبًا يستحق.


Cache-Aside Pattern

أكثر pattern أستخدمه في caching هو cache-aside.

الفكرة تعمل بهذا الشكل:

  1. التطبيق يبحث في الـ cache أولًا.
  2. إذا كانت البيانات موجودة، يرجعها مباشرة.
  3. إذا لم تكن موجودة، يقرأها من قاعدة البيانات.
  4. يخزن النتيجة في الـ cache.
  5. يرجع النتيجة للعميل.

مثال بسيط:

async function getUserProfile(userId) {
  const cacheKey = `user:${userId}:profile`;

  const cachedProfile = await redis.get(cacheKey);

  if (cachedProfile) {
    return JSON.parse(cachedProfile);
  }

  const profile = await database.users.findById(userId);

  await redis.set(cacheKey, JSON.stringify(profile), {
    EX: 300, // 5 minutes
  });

  return profile;
}

هذا pattern بسيط ومرن وسهل الفهم. التطبيق هو الذي يتحكم في وقت القراءة من الـ cache ومتى يحدثه.

لكن هناك نقطة مهمة جدًا: cache invalidation.


Cache Invalidation: الجزء الأصعب

الـ caching سهل إلى أن تتغير البيانات.

لنفترض أننا نخزن user profile لمدة خمس دقائق. ثم قام المستخدم بتغيير اسمه. ماذا يحدث الآن؟

إذا لم نفعل شيئًا، قد يستمر الـ API في إرجاع الاسم القديم حتى تنتهي مدة الـ cache.

هناك أكثر من حل شائع.

استخدام TTL قصير

TTL اختصار لـ “time to live”، وهو يحدد مدة صلاحية العنصر داخل الـ cache.

للبيانات التي تتغير كثيرًا، استخدم TTL قصير. وللبيانات التي نادرًا ما تتغير، استخدم TTL أطول.

مثال:

Product categories: 1 hour
User profile: 5 minutes
Feature flags: 30 seconds
Static content: 1 day or more

الـ TTL القصير يقلل البيانات القديمة، لكنه يزيد الضغط على قاعدة البيانات لأن العناصر تنتهي صلاحيتها بسرعة أكبر.

حذف الـ cache عند تغيير البيانات

عند تحديث البيانات، احذف أو حدث الـ cache المرتبط بها.

await database.users.update(userId, payload);
await redis.del(`user:${userId}:profile`);

هذا غالبًا أدق من انتظار انتهاء الـ TTL.

استخدام version في cache keys

في بعض الأنظمة، يمكن إضافة version داخل cache key.

products:v1:featured
products:v2:featured

هذا مفيد عندما يتغير شكل البيانات المخزنة أو عندما تريد إلغاء مجموعة كاملة من المفاتيح.


مشاكل شائعة في Caching

الـ caching يحسن الأداء، لكنه قد يخلق مشاكل جديدة إذا لم نستخدمه بحذر.

لوحة مراقبة الأداء

Cache stampede

تحدث cache stampede عندما تنتهي صلاحية قيمة مهمة في الـ cache، ثم تأتي طلبات كثيرة في نفس الوقت لإعادة بنائها.

تخيل key عليه ضغط كبير وانتهت صلاحيته فجأة. مئات أو آلاف الطلبات ستفشل في قراءة الـ cache وتذهب مباشرة إلى قاعدة البيانات.

هذا قد يضغط على قاعدة البيانات بشكل خطير.

طرق التقليل من المشكلة:

  • إضافة random jitter إلى TTL.
  • استخدام lock حتى يقوم طلب واحد فقط بإعادة بناء البيانات.
  • تحديث hot keys قبل انتهاء صلاحيتها.
  • استخدام stale-while-revalidate عندما يكون مناسبًا.

Cache penetration

تحدث cache penetration عندما يتم طلب بيانات غير موجودة باستمرار.

مثلًا:

GET /api/products/unknown-id

إذا كان المنتج غير موجود، ولم نخزن هذه النتيجة، فكل طلب سيذهب إلى قاعدة البيانات.

الحل الشائع هو تخزين null أو empty result لفترة قصيرة.

if (!product) {
  await redis.set(cacheKey, JSON.stringify(null), { EX: 60 });
  return null;
}

هذا يحمي قاعدة البيانات من الطلبات المتكررة على بيانات غير موجودة.

Hot key problem

الـ hot key هو مفتاح واحد يحصل على كمية كبيرة جدًا من الطلبات.

مثلًا:

homepage:trending-products

إذا انتهت صلاحيته فجأة، قد تتلقى قاعدة البيانات عددًا ضخمًا من الطلبات.

للتعامل مع هذا:

  • استخدم TTL أطول للـ hot keys.
  • حدثها في الخلفية.
  • جهزها مسبقًا قبل أوقات الضغط.
  • قسم المفاتيح الكبيرة عندما يكون ذلك ممكنًا.

Cache outage

هذه نقطة ينسى البعض التفكير فيها.

ماذا يحدث لو Redis توقف؟

إذا تحولت كل الطلبات فجأة إلى قاعدة البيانات، قد تنهار قاعدة البيانات أيضًا. وهكذا تتحول مشكلة cache إلى outage كامل.

يجب أن يتعامل التطبيق مع فشل الـ cache بهدوء:

  • ضع timeouts لطلبات الـ cache.
  • استخدم circuit breakers عند الحاجة.
  • اجعل fallback محسوبًا.
  • لا ترسل كل الضغط إلى قاعدة البيانات مرة واحدة.
  • راقب صحة الـ cache باستمرار.

الـ cache يجب أن يجعل النظام أسرع، لا أن يصبح single point of failure.


CDN و Browser Caching

الـ caching ليس خاصًا بالـ backend فقط.

للملفات الثابتة مثل الصور، CSS، JavaScript، الخطوط، والفيديوهات، يمكن للـ CDN أن يصنع فرقًا كبيرًا.

الـ CDN يخزن المحتوى بالقرب من المستخدمين حول العالم. بدلًا من تحميل كل المستخدمين للملفات من السيرفر الأساسي، يحصلون عليها من edge location قريب منهم.

هذا يحسن:

  • سرعة تحميل الصفحات.
  • latency عالميًا.
  • الضغط على السيرفر.
  • الاستقرار وقت الزيارات العالية.

وفي تطبيقات الـ frontend، caching headers مهمة جدًا.

مثال:

Cache-Control: public, max-age=31536000, immutable

هذا مناسب للملفات الثابتة التي تحتوي على version في الاسم مثل:

app.8f3a1c.js
styles.91ab2.css

لكن بالنسبة لاستجابات الـ API، يجب أن نكون أكثر حذرًا. ليس كل response يصلح للتخزين في browser أو proxy، خصوصًا إذا كان يحتوي على بيانات خاصة بالمستخدم.


أداء قاعدة البيانات ما زال مهمًا

الـ caching قوي، لكنه لا يجب أن يخفي تصميم قاعدة بيانات سيئ إلى الأبد.

إذا كان query بطيئًا، فالـ cache قد يقلل عدد مرات تشغيله، لكنه سيظل بطيئًا عندما يحدث cache miss.

الأداء الجيد في الـ backend يحتاج أيضًا إلى:

  • indexes صحيحة.
  • SQL queries محسنة.
  • connection pooling.
  • تجنب N+1 queries.
  • pagination للبيانات الكبيرة.
  • background jobs للمهام الثقيلة.
  • read replicas عند الحاجة.
  • patterns واضحة للوصول إلى البيانات.

إذا كان كل طلب يعتمد على query مكلف، فالـ caching قد يساعد لفترة، لكن أصل المشكلة ما زال موجودًا.

أفضل أن أصلح المسار البطيء أولًا، ثم أستخدم الـ caching لتقليل العمل المتكرر.


Compression وحجم البيانات

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

إذا كان الـ API يرجع JSON ضخم بينما الـ frontend يحتاج فقط خمس حقول، فهذا وقت وباندويث مهدور.

طرق التحسين:

  • تفعيل Gzip أو Brotli.
  • إرجاع الحقول التي يحتاجها الـ frontend فقط.
  • استخدام pagination للقوائم الكبيرة.
  • تجنب responses عميقة ومعقدة بدون حاجة.
  • ضغط static assets.
  • minification لملفات frontend.
  • lazy loading للموارد الثقيلة.

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


Monitoring: لا يمكنك التحسين وأنت لا تقيس

مراقبة وتحليلات

من الأخطاء الشائعة أن نعتمد على التخمين.

يقول البعض: “Redis سيجعل النظام أسرع”، لكن لا يقيسون قبل وبعد.

أنت تحتاج إلى metrics.

على الأقل، راقب:

  • cache hit rate.
  • cache miss rate.
  • response time.
  • P95 و P99 latency.
  • عدد database queries.
  • slow queries.
  • Redis latency.
  • error rate.
  • CPU و memory usage.
  • request throughput.

ارتفاع cache hit rate يعني أن الـ cache يساعد فعليًا. أما hit rate ضعيف فقد يعني أن TTL قصير جدًا، أو أن المفاتيح مخصصة أكثر من اللازم، أو أنك تخزن الشيء الخطأ.

للمراقبة، أدوات مثل Prometheus، Grafana، Datadog، New Relic، Elastic APM، و OpenTelemetry مفيدة جدًا.

الهدف بسيط: أن تعرف ما يحدث قبل أن يشتكي المستخدمون.


اعتبارات الأمان

الأداء لا يجب أن يأتي على حساب الأمان.

الـ cache يمكن أن يسبب تسريب بيانات حساسة إذا تم استخدامه بدون حذر.

هذه قواعد أحاول الالتزام بها:

لا تجعل Redis متاحًا للعالم

Redis و Memcached يجب أن يكونا داخل private network. لا يجب فتحهما على الإنترنت العام.

استخدم authentication و access control

فعل Redis authentication و ACLs وكلمات مرور قوية عندما يكون ذلك ممكنًا.

شفر الاتصال عند الحاجة

إذا كانت بيانات الـ cache تتحرك عبر شبكات أو حدود cloud، استخدم TLS.

تجنب تخزين البيانات الحساسة بشكل plain text

كن حذرًا مع:

  • access tokens.
  • بيانات المستخدم الشخصية.
  • بيانات الدفع.
  • الرسائل الخاصة.
  • session information.

إذا كان لا بد من تخزين بيانات حساسة، اجعل TTL قصيرًا وفكر في التشفير.

افصل بيانات الـ tenants بشكل صحيح

في الأنظمة متعددة العملاء، يجب أن تحتوي cache keys على tenant ID أو account ID.

مفتاح سيئ:

settings

مفتاح أفضل:

tenant:123:settings

هذا يمنع إرجاع بيانات عميل إلى عميل آخر بالخطأ.


مثال: Redis Cache بسيط في Node.js

import { createClient } from 'redis';

const redis = createClient({
  url: process.env.REDIS_URL,
});

await redis.connect();

export async function getCachedData(key, fetcher, ttlSeconds = 300) {
  const cached = await redis.get(key);

  if (cached) {
    return JSON.parse(cached);
  }

  const data = await fetcher();

  await redis.set(key, JSON.stringify(data), {
    EX: ttlSeconds,
  });

  return data;
}

الاستخدام:

const products = await getCachedData(
  'products:featured',
  () => productRepository.getFeaturedProducts(),
  300
);

هذا ليس wrapper إنتاجي كامل، لكنه يوضح الفكرة.

في الإنتاج سأضيف:

  • error handling.
  • timeout handling.
  • logging.
  • metrics.
  • cache bypass options.
  • التعامل الآمن مع null values.

مثال: فكرة Caching في NestJS

في NestJS يمكن استخدام cache modules أو Redis integrations حسب الـ stack المستخدم.

مثال مبسط:

@Injectable()
export class ProductService {
  constructor(
    private readonly cacheManager: Cache,
    private readonly productRepository: ProductRepository,
  ) {}

  async getFeaturedProducts() {
    const cacheKey = 'products:featured';

    const cached = await this.cacheManager.get(cacheKey);

    if (cached) {
      return cached;
    }

    const products = await this.productRepository.getFeatured();

    await this.cacheManager.set(cacheKey, products, 300);

    return products;
  }
}

الفكرة نفسها: اقرأ من الـ cache، وإذا لم توجد البيانات اقرأها من المصدر، ثم احفظها.


مثال: Cache-Aside في Go

func GetFeaturedProducts(ctx context.Context, redisClient *redis.Client, repo ProductRepository) ([]Product, error) {
    cacheKey := "products:featured"

    cached, err := redisClient.Get(ctx, cacheKey).Result()
    if err == nil {
        var products []Product
        if json.Unmarshal([]byte(cached), &products) == nil {
            return products, nil
        }
    }

    products, err := repo.GetFeatured(ctx)
    if err != nil {
        return nil, err
    }

    encoded, _ := json.Marshal(products)

    redisClient.Set(ctx, cacheKey, encoded, 5*time.Minute)

    return products, nil
}

هذا أيضًا مبسط. في كود الإنتاج يجب التعامل مع أخطاء Redis بحذر حتى لا يتعطل الـ feature الأساسي بسبب مشكلة في الـ cache.


Roadmap عملي لتحسين الأداء

لو كنت أعمل على تحسين أداء نظام إنتاج، لن أبدأ بشكل عشوائي. سأمشي بخطوات واضحة.

1. قس الأداء أولًا

قبل التحسين، راجع الأرقام الحالية.

ابحث عن:

  • endpoints بطيئة.
  • ضغط عالي على قاعدة البيانات.
  • queries مكلفة.
  • responses كبيرة.
  • طلبات متكررة.
  • صفحات عليها traffic عالي.

2. أضف caching في الأماكن المناسبة

ابدأ بالبيانات الآمنة وعالية التأثير:

  • public content.
  • product categories.
  • feature flags.
  • static configuration.
  • trending items.
  • dashboard summaries.
  • expensive read-only queries.

3. اختر TTL مناسب

لا تستخدم نفس TTL لكل شيء.

كل نوع بيانات يحتاج سياسة مختلفة.

4. احمِ hot keys

جهزها مسبقًا، حدثها قبل انتهاء صلاحيتها، أو اجعلها تعيش مدة أطول.

5. استخدم CDN للـ static assets

هذه غالبًا من أسهل التحسينات في أداء الـ frontend.

6. حسن database queries

أضف indexes، أصلح slow queries، وتجنب N+1 problems.

7. اضغط الاستجابات

فعل Brotli أو Gzip، ولا ترسل بيانات لا يحتاجها العميل.

8. راقب باستمرار

تأكد أن التحسينات تؤثر فعليًا.

9. اختبر تحت ضغط

استخدم أدوات مثل k6، Artillery، JMeter، أو Locust لمحاكاة traffic حقيقي.

10. وثق استراتيجية الـ caching

الفريق يجب أن يعرف ما الذي يتم تخزينه، لمدة كم، وكيف يتم إلغاء التخزين عند الحاجة.


أفكار أخيرة

الـ caching ليس سحرًا، لكنه من أقوى الأدوات لبناء أنظمة إنتاج سريعة.

طبقة cache جيدة يمكن أن تقلل الضغط على قاعدة البيانات، تحسن زمن الاستجابة، وتساعد التطبيق على تحمل traffic أعلى. لكن استراتيجية caching سيئة يمكن أن تسبب بيانات قديمة، أخطاء مخفية، مشاكل أمان، وحتى outages.

لذلك الهدف ليس “خزن كل شيء”.

الهدف هو تخزين البيانات الصحيحة، لمدة صحيحة، مع monitoring جيد و fallback محسوب.

كمطور full-stack، أرى أن caching جزء من بناء تجربة مستخدم أفضل. المستخدم لن يعرف أن Redis موجود، أو أن CDN خدم الصورة، أو أن query لم يتم تشغيله. هو فقط سيشعر أن التطبيق سريع وسلس وموثوق.

وهذا هو المطلوب.

جدول المحتويات

  • لماذا يعتبر Caching مهمًا؟
  • الفكرة الأساسية
  • In-Memory Cache أم Distributed Cache؟
  • 1. In-memory cache
  • 2. Distributed cache
  • Cache-Aside Pattern
  • Cache Invalidation: الجزء الأصعب
  • استخدام TTL قصير
  • حذف الـ cache عند تغيير البيانات
  • استخدام version في cache keys
  • مشاكل شائعة في Caching
  • Cache stampede
  • Cache penetration
  • Hot key problem
  • Cache outage
  • CDN و Browser Caching
  • أداء قاعدة البيانات ما زال مهمًا
  • Compression وحجم البيانات
  • Monitoring: لا يمكنك التحسين وأنت لا تقيس
  • اعتبارات الأمان
  • لا تجعل Redis متاحًا للعالم
  • استخدم authentication و access control
  • شفر الاتصال عند الحاجة
  • تجنب تخزين البيانات الحساسة بشكل plain text
  • افصل بيانات الـ tenants بشكل صحيح
  • مثال: Redis Cache بسيط في Node.js
  • مثال: فكرة Caching في NestJS
  • مثال: Cache-Aside في Go
  • Roadmap عملي لتحسين الأداء
  • 1. قس الأداء أولًا
  • 2. أضف caching في الأماكن المناسبة
  • 3. اختر TTL مناسب
  • 4. احمِ hot keys
  • 5. استخدم CDN للـ static assets
  • 6. حسن database queries
  • 7. اضغط الاستجابات
  • 8. راقب باستمرار
  • 9. اختبر تحت ضغط
  • 10. وثق استراتيجية الـ caching
  • أفكار أخيرة
BackendNode.jsNestJSGoCachingPerformanceRedisCDNDatabase OptimizationScalabilityProduction Systems

منشورات مقترحة

بناء واجهات API مرنة: Retry و Circuit Breaker و Rate Limiting
06 يناير 202612 دقيقة

بناء واجهات API مرنة: Retry و Circuit Breaker و Rate Limiting

مقال عملي من منظور Full-Stack Web Developer عن كيفية بناء APIs تتحمل أعطال الإنتاج باستخدام timeouts و retries و circuit breakers و rate limiting، مع أمثلة في Node.js و NestJS و Go.

تطوير الواجهة الخلفية
نود جي إسنود جي إسنست جي إسنست جي إسجينجينهندسة الباك إندهندسة الباك إند
اقرأ المزيد
DevelopmentDesignAPIBackendResilienceDistributed SystemsNode.jsNestJSGoRate LimitingCircuit BreakerRetry Pattern
React2Shell: How I Would Handle a Critical RSC Vulnerability as a Full-Stack Developer
الترجمة العربية غير متوفرة بعد
30 أبريل 20269 دقيقة

React2Shell: How I Would Handle a Critical RSC Vulnerability as a Full-Stack Developer

A practical Full-Stack developer article about React2Shell, the React Server Components vulnerability wave, and how I would detect, patch, verify, rotate secrets, and harden a real Next.js production app.

نود جي إسنود جي إسهندسة الباك إندهندسة الباك إندريأكتريأكتنكست جي إسنكست جي إس
اقرأ المزيد
DevelopmentReactNext.jsReact Server ComponentsReact2ShellCVEWeb SecurityApplication SecurityFull-StackIncident ResponseCI/CDDependency SecuritySecrets Management

مشاريع ذات صلة

إي تك باي
إي تك باي
  • PostgreSQLPostgreSQL
  • نست جي إسنست جي إس
  • ريأكتريأكت

E-techPay هو منصة تجارة إلكترونية كاملة تجعل التسوق عبر الإنترنت سهلًا وآمنًا. إنه سريع، موثوق، ومصمم لتقديم أفضل تجربة تسوق.

اقرأ اكثر
arabic title
arabic title
  • بريزمابريزما
  • نود جي إسنود جي إس
  • نكست جي إسنكست جي إس

here is a small descipriot

اقرأ اكثر

شهادات ذات صلة

تطوير الواجهة الخلفية باستخدام ASP.Net

تطوير الواجهة الخلفية باستخدام ASP.Net

Board Infinity

يناير ٢٠٢٥

تفاصيل
جافا سكريبت: الدورة الكاملة 2024: من الصفر إلى الخبير!

جافا سكريبت: الدورة الكاملة 2024: من الصفر إلى الخبير!

Udemy

مارس ٢٠٢٤

تفاصيل
اعمل معي