تصور کنید هر بار برای تست یک ویژگی جدید، باید ۳ ساعت منتظر بمانید تا دادههای دیتابیس کپی و پاکسازی شوند؛ حالا این فرآیند به یک اسکریپت ۹۰ ثانیهای تبدیل شده است. یک تیم مهندسی با استفاده از Claude Code برای ساخت یک مولد دادههای مصنوعی (Seed Generator) که نسبت به طرح دیتابیس (Schema-aware) آگاه است، نه تنها ریسک نشت اطلاعات کاربران را به صفر رساند، بلکه توانست سناریوهایی را شبیهسازی کند که هنوز در دنیای واقعی رخ ندادهاند.
بسیاری از تیمهای توسعه از روشی ناکارآمد و اصطلاحاً «چرخ شکسته» برای دادههای تست استفاده میکنند: کپی کردن دیتابیس تولید (Production) و تلاش برای حذف یا ماسک کردن اطلاعات شخصی. این فرآیند بهشدت شکننده است؛ زیرا هر ستون جدید که به دیتابیس اضافه شود، نیاز به بهروزرسانی دستی اسکریپتهای پاکسازی دارد. یک اشتباه کوچک یا یک غفلت در بهروزرسانی، میتواند دادههای واقعی کاربران را به محیطهای استیجینگ (Staging) — که معمولاً کنترلهای دسترسی ضعیفتری دارند — نشت دهد. به گزارش وبسایت dev.to، این تیم تنها در یک فصل، دو مورد نزدیک به نشت داده (Near-miss) را در مرحله بازبینی کد شناسایی کرد. این یعنی دو مورد بیشتر از آنچه قابل تحمل باشد.
هزینههای پنهان کپیهای دیتابیس تولید
همانطور که در تحلیلهای پیشین ما دربارهی امنیت مدلهای زبانی و مدیریت دادهها اشاره کردیم، اتکا به دادههای واقعی در محیطهای غیرتولیدی همواره یک نقطه ضعف امنیتی است. اما فراتر از حریم خصوصی، کپیهای دیتابیس تولید اساساً محدود هستند زیرا فقط «گذشته» را در بر میگیرند. وقتی ویژگی جدیدی میسازید — مثلاً یک جریان پرداخت جدید با مدل قیمتگذاری که هنوز مستقر نشده است — دادههای تولیدی هیچ ردیفی برای تست این منطق جدید ندارند. در واقع، یک کپی دیتابیس نمیتواند «آینده» را تست کند.
علاوه بر این، حجم این کپیها اغلب بهطور غیرضروری زیاد است. این تیم متوجه شد برای تست ویژگیهایی که فقط به چند صد ردیف دادهی دقیق نیاز دارند، میلیونها ردیف را بازیابی میکنند. این حجم زیاد (Bloat) باعث میشد چرخه بهروزرسانی از ابتدا تا انتها حدود ۳ ساعت طول بکشد. در نتیجه، رفرش دادهها بهندرت (مثلاً ماهی یکبار) انجام میشد. این موضوع باعث میشد دادههای استیجینگ با واقعیت فاصله بگیرند (Drift) و تستها به ردیفهای خاص و قدیمی وابسته شوند. در نهایت، عبارت «در استیجینگ درست کار میکند» عملاً بیمعنی شد.
از سوی دیگر، توابع کارخانهای (Factory Functions) که بهصورت دستی نوشته میشوند، معمولاً با گذشت زمان و تغییر Schema دیتابیس، فاسد میشوند. چون این توابع معمولاً برای هر ویژگی یکبار نوشته میشوند، هیچکس متوجه این فاصله نمیشود تا زمانی که یک Migration واحد، بهطور همزمان ۳۰ مورد از آنها را خراب کند.
چالشهای فنی و معماری
پروژه با یک محدودیت بزرگ روبرو بود: یک طرح (Schema) پیچیده شامل بیش از ۴۰ جدول. این محیط دارای شبکهای متراکم از کلیدهای خارجی (Foreign Keys)، محدودیتهای چک (Check Constraints) و چندین رابطه چندریختی (Polymorphic Relationships) بود که فقط در کد اپلیکیشن تعریف شده بودند. هر مولدی که این محدودیتها را رعایت نمیکرد، دادههایی تولید میکرد که اپلیکیشن را بلافاصله متوقف میکرد.
برای حل این مشکل، مهندس مربوطه از Claude Code (نسخه ۱.x) استفاده کرد تا خودِ «مولد» را بسازد. با بهرهگیری از PostgreSQL 16 و Python 3.12، بهجای نوشتن دستی منطق تولید داده برای ۴۰ جدول، از هوش مصنوعی خواست تا طرح دیتابیس را تحلیل (Introspect) کرده و مولدهای هر جدول را برای بازبینی انسانی بنویسد.
بر اساس مستندات این پروژه، فرآیند در پنج مرحله مجزا اجرا شد:
تحلیل طرح (Schema Introspection): توسعهدهنده بهجای اتکا به حافظه، خروجی کامل
information_schemaدیتابیس PostgreSQL 16 را به عنوان یک فایل زمینه (Context) ساختاریافته به مدل داد. این شامل انواع ستونها، قابلیت Null بودن، تعاریف Enum و یک کوئری خاص برای استخراج روابط کلید خارجی بود:SELECT tc.table_name, kcu.column_name, ccu.table_name AS references_table, ccu.column_name AS references_column FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name WHERE tc.constraint_type = 'FOREIGN KEY';
این مرحله حیاتی بود؛ بدون این دامپ واقعی، هوش مصنوعی «داستانهایی باورپذیر اما ساختگی» تولید میکرد. اما با این دادهها، مدل توانست محدودیتهای چکی را که حتی خود توسعهدهنده فراموش کرده بود، بهدرستی شناسایی کند.نقشهبرداری وابستگیها: از آنجایی که کلیدهای خارجی یک گراف جهتدار ایجاد میکنند، ابزار از یک مرتبسازی توپولوژیک (Topological Sort) استفاده میکند تا مطمئن شود جداول والد قبل از فرزندان پر میشوند. پیادهسازی این بخش از یک حلقه
whileبرای حل وابستگیها استفاده کرد و در صورت شناسایی ارجاع چرخشی، خطایCycleErrorصادر میکرد. این فرآیند در واقع یک چرخه واقعی در FKها (دو جدول که از طریق Deferred Constraints به هم ارجاع میدادند) را پیدا کرد که سالها نادیده گرفته شده بود.توزیعهای نامتقارن (Skewed Distributions): برای جلوگیری از بیفایده بودن دادههای تصادفی یکنواخت، مولد از مشخصات توزیع استفاده میکند. دادههای یکنواخت نمیتوانند طرحهای کوئری (Query Plans) را تحریک کنند که در بارهای سنگین باعث کرش سیستم میشوند. تیم مشخصات نامتقارنی مانند
ORDERS_PER_CUSTOMERرا پیاده کرد که در آن p50 برابر با ۲ سفارش، p95 برابر با ۴۰ و p999 برابر با ۲۵,۰۰۰ سفارش است. این تضمین میکند که «حسابهای غولپیکر» (Whale Accounts) که معمولاً باعث شکست سیستم میشوند، در هر اجرا حضور داشته باشند.حالتهای لبهای درجهیک (First-Class Edge Cases): سیستم لیستی از ردیفهای آسیبشناختی (Pathological Rows) را که بهصورت دستی انتخاب شدهاند، در کنار دادههای حجیم تصادفی وارد میکند. این موارد شامل موارد زیر است:
- نامهای نمایشی خالی برای تست ردیفهای قدیمی (Legacy).
- نامهایی با ۳۰۰۰ کاراکتر از علائم ترکیبی (Combining Diacritics) برای بررسی محدودیتهای طول.
- ایمیلهایی با فرمتهای پیچیده (مانند
[email protected]). - ردیفهای بسیار قدیمی که در زمان EPOCH ایجاد شدهاند تا دادههای پیش از Migration تست شوند.
- حالتهای متناقض، مانند ردیفی که همزمان
deleted_at=NOWوactive=Trueباشد.
بذرگذاری قطعی (Deterministic Seeding): هر اجرا از یک مولد اعداد تصادفی با بذر (Seed) استفاده میکند. با اجرای دستور
./seed --seed 42 --scale 0.1برای دادههای متناسب با لپتاپ یا--scale 1.0برای دادههای متناسب با استیجینگ، هر توسعهدهنده دقیقاً همان «افراد» و دادهها را میبیند. این کار عبارت «نمیتوانم باگ را بازتولید کنم» را به یک ارجاع دقیق تبدیل میکند: «بذر ۴۲، مشتری شماره ۱۸۴۷».
نتایج و دستاوردهای عملیاتی
زمان کل ساخت این سیستم تقریباً چهار روز بود که بیشتر آن صرف بازبینی انسانی و کدگذاری محدودیتهایی شد که فقط در کد اپلیکیشن وجود داشتند. خط لوله نهایی از این مسیر پیروی میکند: طرح PostgreSQL $
ightarrow$ دامپ محدودیتها $
ightarrow$ تولید توسط Claude Code $
ightarrow$ بازبینی انسانی/مشخصات توزیع $
ightarrow$ مرتبسازی توپولوژیک $
ightarrow$ درج قطعی $
ightarrow$ استیجینگ/CI/لپتاپها.
دو هفته پس از استقرار، تیم کل خط لوله پاکسازی (Anonymization) خود را حذف کرد. اکنون محیط استیجینگ کاملاً با دادههای مصنوعی اجرا میشود و توسعهدهندگان هیچ تفاوتی در کاربردی بودن دادهها حس نمیکنند. زمان رفرش از ۳ ساعت به ۹۰ ثانیه کاهش یافته است.
این تغییر، فرض بنیادی محیطهای استیجینگ را عوض کرد: دادهها دیگر یک اثر ایستا برای کپی کردن نیستند، بلکه برنامهای هستند که باید اجرا شوند. با انتقال دروازه کیفیت به مرحله بازبینی کدِ مولد، تیم تضمین کرد که دادهها بهطور خودکار با Schema تکامل مییابند. کد، اثر اصلی است و Schema بهترین پرامپت موجود است.
برای توسعهدهنده، این یعنی «شعاع تخریب» (Blast Radius) یک نشت احتمالی در استیجینگ اکنون صفر است. برای کسبوکار، این یعنی هزینه رعایت قوانین حریم خصوصی برای محیطهای غیرتولیدی از بین رفته است. بزرگترین پیروزی، نه سرعت، بلکه حذف کامل دادههای واقعی کاربران از چرخه تست بود.
درسهای آموخته شده
از طریق این فرآیند، تیم چندین اصل کلیدی برای تولید داده با کمک هوش مصنوعی شناسایی کرد:
۱. مولد را تولید کنید، نه دادهها را. ردیفهای ایستا فاسد میشوند؛ اما یک برنامه آگاه از Schema، قابل مقایسه (Diffable) و بازتولید است.
۲. واقعگرایی در توزیعها نهفته است. دادههای یکنواختی که فقط کلیدهای خارجی را رعایت میکنند، از محدودیتها عبور میکنند اما هدف تست را برآورده نمیکنند. واقعگرایی نیازمند نابرابری حسابهای غولپیکر و حسابهای خالی است.
۳. قطعی بودن (Determinism) بر واقعگرایی برتری دارد. در حالی که محیط تولید واقعی تکرارپذیر نیست، اما توانایی به اشتراک گذاشتن یک شماره بذر (Seed) برای دیباگ کردن، بسیار ارزشمندتر از واقعگرایی کامل است.
تکرارهای آینده
تیم اکنون روی دو بهبود کار میکند. اول، قصد دارند Migrationهای Schema را مستقیماً به مولد در CI متصل کنند؛ بهطوری که هر Migrationی که تولید داده را خراب کند، باعث شکست Build شود و ابزار Seed را به یک تست زنده برای خودِ Schema تبدیل کند. دوم، قصد دارند به مولد آموزش دهند تا با تحلیل گزارشهای اخیر باگها، ردیفهای جدیدی برای حالتهای لبهای (Edge-case) پیشنهاد دهد تا هر حادثه در محیط تولید، به بخشی دائمی از دادههای Seed تبدیل شود.
گام بعدی شما
- اگر از کپی دیتابیس تولید برای تست استفاده میکنید، ابتدا یک مولد ساده برای یکی از جداول پیچیده خود با Claude Code بسازید تا قدرت تحلیل Schema را بسنجید.
- توزیع دادههای خود را بررسی کنید؛ بهجای دادههای تصادفی یکنواخت، «حسابهای غولپیکر» را شبیهسازی کنید تا نقاط شکست سیستم را بیابید.
- از بذرگذاری (Seeding) برای تکرارپذیر کردن باگها در تیم توسعه استفاده کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو