Strangler Pattern: ধাপে ধাপে পুরোনো system বদল
Strangler Migration
এই পাঠের সূচিপত্র
এই পাঠে যা শিখবেন
- একবারে rewrite-এর ঝুঁকি কমান
- Route ও data ownership ধাপে সরান
- Rollback এবং reconciliation পরিকল্পনা করুন
সমস্যা দিয়ে শুরু
পুরোনো Laravel shop-এর catalog module বদলাতে হবে। পুরো system rewrite করতে গেলে ছয় মাস feature বন্ধ থাকবে, আর একদিনে সব traffic নতুন code-এ দিলে hidden behavior ধরা পড়বে না। ছোট boundary দিয়ে migration শুরু করা দরকার।
সহজ করে বুঝি
Strangler migration পুরোনো application-এর সামনে routing seam তৈরি করে কিছু capability নতুন implementation-এ সরায়। পুরোনো system ধীরে ছোট হয়। Proxy, feature flag বা adapter traffic split করতে পারে। Read migration আর write ownership migration আলাদা; একই data-তে অনিয়ন্ত্রিত dual write বিপজ্জনক।
পরিচিত একটি উপমা
দোকান চালু রেখেই একেকটি বিভাগ নতুন ভবনে সরানো হয়। Entrance-এ নির্দেশনা থাকে কোন পণ্যের জন্য কোথায় যাবেন। দুটি দোকানে একই cash register স্বাধীনভাবে চালালে হিসাব মেলে না; টাকা নেওয়ার মালিকানা স্পষ্ট রেখে transfer করতে হয়।
নকশাটি দেখুন
Diagram লোড হচ্ছে…
Diagram-এর text flow দেখুন
flowchart LR C[Customers] --> R[Routing Facade] R -->|Catalog reads| N[New Catalog] R -->|Checkout writes| O[Legacy Laravel] O --> D[(Authoritative DB)] D -->|Backfill and changes| N
Facade path বা flag দেখে request পাঠায়। Catalog reads নতুন service পায়, checkout পুরোনো implementation-এ থাকে। Data backfill-এর সঙ্গে নতুন changes capture করতে হয়। Schema ও ownership readiness ছাড়া write route switch করা হয় না। Rollback route বদলালেও data compatibility থাকতে হবে।
PHP ও Laravel-এ প্রয়োগ
Laravel controller adapter fragment; new catalog service আগে configure করা trusted internal URL। Feature flag stable cohort থেকে আসে, random per-request নয়। এখানে read migration দেখানো হয়েছে; timeout হলে legacy read fallback করতে পারে, side-effectful write blind replay করা যাবে না।
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\ConnectionException;
if (! config('features.new_catalog_reads')) {
return $legacyCatalog->show($productId);
}
try {
$response = Http::baseUrl(config('services.catalog.url'))
->connectTimeout(1)->timeout(2)
->get('/products/'.$productId);
$response->throw();
return response()->json($response->json());
} catch (ConnectionException $exception) {
return $legacyCatalog->show($productId);
}
// Non-connection errors require an explicit policy; do not hide every defect.এটি PHP 8.3+ ও Laravel 12-এর শিক্ষামূলক fragment; সম্পূর্ণ application নয়। সংশ্লিষ্ট route-এ authentication ও resource authorization প্রয়োগ করতে হবে। নিচের অনুশীলনে failure ইচ্ছা করে তৈরি করুন; শুধু সফল response দেখে correctness ধরে নেবেন না।
সুবিধা, সীমাবদ্ধতা ও trade-off
Incremental release risk ও feedback cycle ছোট করে। Temporary facade ও duplicate read infrastructure খরচ বাড়ায়। Migration শেষ করার deadline না থাকলে permanent hybrid complexity তৈরি হয়। Big-bang rewrite কখনও ছোট replaceable subsystem-এ মানাতে পারে, কিন্তু evidence চাই।
সাধারণ ভুল
- দুই database-এ write করে সব সময় মিলবে ধরে নেওয়া।
- Rollback route আছে বলে নতুন data format পুরোনো code বুঝবে ভাবা।
- Shadow traffic দিয়ে payment write পুনরায় চালানো।
আরও একটু গভীরে
Shadow reads response compare করতে পারে, কিন্তু personal data ও load impact বিবেচনা করুন। Backfill snapshot-এর পরে change stream catch-up complete না হলে নতুন read stale হতে পারে। Cutover criteria measurable করুন: mismatch rate, latency এবং unprocessed change age।
শুধু internal staff cohort-এ নতুন catalog চালান। Product price ও visibility দুদিকে compare করুন। Error threshold ছাড়ালে route ফেরান। নতুন service-এ লেখা data পুরোনো code-এর জন্য compatible না হলে rollback-এর বদলে forward repair লাগতে পারে।
মনে রাখুন
- Migration unit ছোট রাখুন।
- Write owner সব সময় একজন।
- Rollback-এর data শর্ত লিখুন।
নিজে চেষ্টা করুন
Inventory module migration-এর চার phase লিখুন: read shadow, read cutover, write ownership change এবং legacy removal। প্রতিটির exit criterion দিন।
নিজের বোঝা যাচাই করুন
1. Proxy দিলেই migration?
না। Data ownership, compatibility ও operational retirement পরিকল্পনা ছাড়া শুধু routing বদল হয়।
2. Read fallback নিরাপদ?
Side effect নেই এবং semantics মেলে হলে তুলনামূলক সহজ; stale data policy এখনও দরকার।
3. Write fallback কেন কঠিন?
প্রথম request commit হয়েছে কি না অজানা হতে পারে, দ্বিতীয় implementation duplicate effect করতে পারে।
4. Dual write সমাধান?
Atomicity ছাড়া partial failure আসে; outbox, CDC বা এক authoritative writer দিয়ে transition ভালো।
5. শেষ ধাপ কী?
Legacy traffic শূন্য, dependency সরানো এবং পুরোনো data/infra retirement যাচাই করা।
আরও পড়ুন
এই পাঠের কুইজ
এই পাঠ থেকে ২টি প্রশ্ন। উত্তর দিয়ে ব্যাখ্যা দেখুন; অধ্যায়ের কুইজ আলাদাভাবে দিতে হবে।
এই পাঠের ২টি প্রশ্নের উত্তর দিন। পাস করতে দুটিই সঠিক হতে হবে।
জমা দেওয়ার পর সঠিক উত্তর ও ব্যাখ্যা দেখবেন। ফলাফল এই ব্রাউজারে সংরক্ষিত থাকবে। অনুশীলনের ফল অধ্যায় সম্পন্নের হিসাবে যোগ হয় না।
অগ্রগতি এই ব্রাউজারে সংরক্ষিত থাকে। শুধু পাঠ খুললে সম্পন্ন হয় না।