معماری داده با Supabase Postgres و ORM تایپسیف
Postgres به عنوان ستون فقرات داده، Supabase به عنوان لایه عملیاتی و امنیتی، Drizzle به عنوان قرارداد تایپسیف schema، همراه با RLS، pooling و کانالهای realtime
Supabase Postgres به عنوان ستون فقرات داده
حقیقت رابطهای، ابزار عملیاتی، سیاست امنیتی و جریان زنده داده
لایه دیتابیس نباید فقط یک مخزن منفعل پشت اپلیکیشن باشد. در بکاند مقیاسپذیر، Postgres مالک حقیقت رابطهای سیستم است: entityهای نرمالشده، constraintها، transactionها، indexها و رفتار query. Supabase روی همین هسته، سطح عملیاتی لازم را اضافه میکند: policyهای آگاه از auth، کانالهای realtime، ابزارهای visibility، primitiveهای ذخیرهسازی و تجربه مدیریتی بهتر برای دیتابیس.
در این معماری، منطق محصول بالای دیتابیس میماند، اما integrity داده داخل کدهای پراکنده اپلیکیشن تکرار نمیشود. اپلیکیشن از طریق مرزهای تایپشده سرور درخواست تغییر state میدهد؛ Postgres سازگاری و رابطهها را enforce میکند؛ و Supabase بخشهایی را که باید realtime، policy-aware یا عملیاتی باشند قابل استفاده میکند. نتیجه، لایه دادهای است که مثل control plane عمل میکند: پایدار، قابل مشاهده، محافظتشده و آماده رشد تدریجی.
همگامسازی ساختار داده با ORM تایپسیف
یکپارچگی پایگاهداده و مدلهای برنامه با Drizzle ORM
ORM نباید به یک لایه جادویی تبدیل شود که SQL را پشت interfaceهای مبهم پنهان میکند. schema باید برای Postgres صریح، برای مهندس خوانا، و برای اپلیکیشن تایپشده باشد. Drizzle مدل دیتابیس را به قرارداد TypeScript تبدیل میکند تا نام جدول، نام ستون، relationها و shape خروجیها بیصدا از کد جدا نشوند.
در این مدل، فایلهای schema، migrationهای تولیدشده و query builder همزمان حرکت میکنند. تغییر یک ستون فقط ویرایش دیتابیس نیست؛ به یک migration قابل review و یک تغییر compile-time در کد تبدیل میشود. این کار خطاهای runtime را کم میکند، refactor را امنتر میسازد و مزیت SQL را حفظ میکند، بدون اینکه اعتماد تایپی end-to-end قربانی شود.
مدیریت اتصالات با سیستم کانکشنپولینگ
pgBouncer به عنوان شیر کنترل فشار بین concurrency وب و sessionهای Postgres
runtime وب میتواند تعداد زیادی request کوتاهعمر بسازد، اما connection دیتابیس مثل socket ساده HTTP ارزان نیست. هر session در Postgres حافظه، ظرفیت پردازشی، وضعیت transaction و bookkeeping مربوط به lockها را مصرف میکند. اگر هر request مستقیماً connection خودش را باز کند، spike ترافیک قبل از اینکه خود query bottleneck شود، میتواند به طوفان connection تبدیل شود.
pgBouncer جلوی Postgres مثل شیر کنترل فشار عمل میکند. در حالت transaction pooling، تعداد زیادی request سمت کلاینت میتوانند روی تعداد کمتری session واقعی دیتابیس multiplex شوند و overflow به جای فشار مستقیم روی دیتابیس، وارد صف کنترلشده شود. هدف فقط سرعت نیست؛ هدف پیشبینیپذیری عملیاتی است: تعداد session قابل کنترل، spike امنتر هنگام deploy، مصرف حافظه پایدار و مرز منابع روشن بین اپلیکیشن و هسته داده.
امنیت داده در لایه پایگاهداده (Row-Level Security)
predicate مالکیت، سیاستهای USING / WITH CHECK و authorization در خود دیتابیس
Authorization نباید فقط به handlerهای اپلیکیشن وابسته باشد. یک route ممکن است درست طراحی شده باشد، اما یک filter فراموششده، مسیر admin ناامن، یا bug کوچک بتواند سطرهای اشتباه را برگرداند. Row-Level Security تصمیم نهایی دسترسی را به خود Postgres منتقل میکند: query میتواند اجرا شود، اما هر سطر خروجی هنوز باید از policy عبور کند.
در Supabase این موضوع برای schemaهای exposed و Data API اهمیت بیشتری دارد. policy قوی فقط به `TO authenticated` اکتفا نمیکند؛ نقش کاربر باید با predicate مالکیت یا رابطهای مثل `auth.uid() = owner_id` ترکیب شود. برای mutationها هم `USING` و `WITH CHECK` باید کنار هم باشند تا کاربر نه بتواند سطری را که نباید ببیند تغییر دهد، نه بتواند owner یا scope سطر را به محدوده غیرمجاز منتقل کند.
سیستم ارتباطات بلادرنگ وبسوکت (Real-time Channels)
Postgres Changes، سیگنالهای Broadcast، وضعیت Presence و تحویل scopeشده روی WebSocket
Realtime نباید راه فرار از مدل داده باشد. این لایه فقط مسیر تحویل stateهایی است که منبع و scope روشن دارند. به جای اینکه کلاینت برای فهمیدن تغییرات دائماً polling کند، بکاند میتواند تغییرات معتبر دیتابیس، سیگنالهای موقت Broadcast یا وضعیت Presence را از طریق کانالهای WebSocket فقط به بخشهایی از UI برساند که واقعاً به آن state وابستهاند.
Supabase Realtime سه الگوی مهم را قابل استفاده میکند: Postgres Changes برای mutationهای پایدار جدول، Broadcast برای eventهای موقت هماهنگی، و Presence برای وضعیت مشترک کاربر یا session. نکته معماری در کنترل است: کانال realtime باید فیلترشده، scopeشده و همراه با قواعد authorization باشد تا UI زنده و سریع شود، بدون اینکه هر تغییر دیتابیس به notification عمومی تبدیل شود.
آماده ورود به فاز ۵: دواپس و زیرساخت توزیعشده هستید؟
در فاز بعدی به معماری صفهای غیرهمزمان BullMQ، لایه Caching با Redis، مانیتورینگ تلهمتری، کانتینرسازی Docker و استقرار بدون اختلال (Zero-Downtime) خواهیم پرداخت.