كيف بنيت نظام SaaS يتحمل 100 ألف مستخدم؟
كيف بنيت نظام SaaS يتحمل 100 ألف مستخدم؟
الدليل الاحترافي من إعداد علاء عامر - خبير تطوير الويب والتصميم
التوسع في نظام SaaS من صفر لـ 100 ألف مستخدم نشط تحدٍّ مختلف تمامًا عن مجرد بنائه. هذه رحلة حقيقية في القرارات والمقايضات والمعمارية التي جعلت ذلك ممكنًا.
2️⃣ Multi-Tenancy: قاعدة بيانات واحدة أم منفصلة؟
أكبر قرار في معمارية SaaS. اخترت قاعدة بيانات مشتركة مع عزل المستأجرين — الأكثر كفاءة في التكلفة عند التوسع.
-- كل جدول يحتوي على tenant_id
CREATE TABLE projects (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Index مركّب للأداء
CREATE INDEX idx_projects_tenant ON projects (tenant_id, created_at DESC);
-- Row-Level Security للأمان
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON projects
USING (tenant_id = current_setting('app.current_tenant')::UUID);
ضبط سياق المستأجر مع كل طلب:
// middleware/tenant.ts
export async function tenantMiddleware(req, res, next) {
const tenant = await resolveTenantFromHostname(req.hostname);
if (!tenant) return res.status(404).json({ error: "المستأجر غير موجود" });
// ضبط متغير الجلسة في PostgreSQL
await db.query(`SET LOCAL app.current_tenant = '${tenant.id}'`);
req.tenant = tenant;
next();
}
4️⃣ استراتيجية الكاش مع Redis
استخدم الكاش بقوة — لكن للأشياء الصحيحة.
// lib/cache.ts
import { Redis } from "ioredis";
const redis = new Redis(process.env.REDIS_URL);
// Wrapper للكاش العام
export async function cached<T>(
key: string,
ttlSeconds: number,
fetcher: () => Promise<T>,
): Promise<T> {
const hit = await redis.get(key);
if (hit) return JSON.parse(hit) as T;
const value = await fetcher();
await redis.setex(key, ttlSeconds, JSON.stringify(value));
return value;
}
// إلغاء الكاش بالنمط
export async function invalidatePattern(pattern: string) {
const keys = await redis.keys(pattern);
if (keys.length > 0) await redis.del(...keys);
}
الاستخدام داخل Route:
// api/projects.ts
app.get("/api/projects", async (req, res) => {
const { tenantId } = req.tenant;
const projects = await cached(
`tenant:${tenantId}:projects`,
60, // TTL 60 ثانية
() =>
db.query(
"SELECT * FROM projects WHERE tenant_id = $1 ORDER BY created_at DESC",
[tenantId],
),
);
res.json(projects.rows);
});
طبقات الكاش التي استخدمتها:
- L1: In-memory (node-cache) — دون ميلي ثانية، لكل Process
- L2: Redis — مشترك بين كل الـ Instances، ميلي ثوانٍ
- L3: CDN Edge Cache — للردود العامة الثابتة
6️⃣ المصادقة وتحديد المعدل والأمان
// middleware/auth.ts
import jwt from "jsonwebtoken";
export function authenticate(req, res, next) {
const token = req.headers.authorization?.split(" ")[1];
if (!token) return res.status(401).json({ error: "غير مصرح" });
try {
const payload = jwt.verify(token, process.env.JWT_SECRET) as JWTPayload;
req.user = payload;
next();
} catch {
return res.status(401).json({ error: "رمز غير صالح" });
}
}
// تحديد المعدل لكل مستأجر
import rateLimit from "express-rate-limit";
import RedisStore from "rate-limit-redis";
export const apiLimiter = rateLimit({
windowMs: 60 * 1000, // نافذة دقيقة واحدة
max: 300, // 300 طلب في الدقيقة لكل مستأجر
keyGenerator: (req) => req.tenant?.id ?? req.ip,
store: new RedisStore({ client: redis }),
handler: (req, res) => {
res.status(429).json({ error: "تجاوزت الحد المسموح. يرجى التباطؤ." });
},
});
الملخص
في هذا المقال تعلمنا:
✅ أسس البنية التحتية واختيار التقنيات ✅ Multi-Tenancy مع PostgreSQL Row-Level Security ✅ تصميم قاعدة البيانات وConnection Pooling ✅ الكاش متعدد الطبقات مع Redis ✅ طوابير المهام في الخلفية باستخدام Bull ✅ المصادقة وتحديد المعدل وأنماط الأمان ✅ هيكل SaaS كامل وجاهز للإنتاج
أكبر درس تعلمته: مشاكل الأداء عند التوسع قابلة للحل دائمًا — لكن فقط إذا لم تحاربك معماريتك. ابنِ الأساس الصحيح مبكرًا.
📩 هل تحتاج مساعدة في تصميم معمارية منتجك SaaS؟
قسم المقالة
كيف بنيت نظام SaaS يتحمل 100 ألف مستخدم؟
تجربة حقيقية في بناء SaaS قابل للتوسع: Multi-Tenancy، تصميم قاعدة البيانات، الكاش، الطوابير، المصادقة، والمراقبة — مع الدروس المستفادة.
التواصل والاستشارة
تواصل مباشر عبر الواتساب أو الهاتف لفهم احتياجات مشروعك بدقة.
التخطيط والجدولة
وضع خطة عمل واضحة مع جدول زمني محدد لكل مرحلة من المشروع.
البرمجة والتطوير
تطوير المشروع بأحدث التقنيات لضمان الأداء والأمان العاليين.
المراجعة والتسليم
ختبار شامل ومراجعة دقيقة قبل التسليم النهائي للمشروع.