expand/contract প্যাটার্ন ব্যবহার করে জিরো-ডাউনটাইম স্কিমা পরিবর্তন শিখুন: নিরাপদে কলাম যোগ করুন, ব্যাচে ব্যাকফিল করুন, কম্প্যাটিবল কোড ডিপ্লয় করুন, তারপর পুরনো পাথ মুছুন।

ডাটাবেস পরিবর্তনের ফলে হওয়া ডাউনটাইম সবসময় স্পষ্ট বা পরিস্কার আউটেজের মতো নয়। ব্যবহারকারীর কাছে এটা হতে পারে এমন যে একটি পেজ অনন্তকাল লোড হচ্ছে, চেকআউট ব্যর্থ হচ্ছে, বা অ্যাপে হঠাৎ "কিছু ভুল হয়েছে" দেখা যাচ্ছে। টিমের দৃষ্টিতে এটা আসে এলার্ট, বাড়তে থাকা এরর রেট, এবং_failed writes_–এর ব্যাকলগ হিসেবে যেগুলো ক্লিনআপ দরকার।
স্কিমা পরিবর্তন ঝুঁকিপূর্ণ কারণ ডাটাবেস আপনার অ্যাপের প্রতিটি চলমান ভার্সনের দ্বারা শেয়ার করা হয়। রিলিজের সময় প্রায়ই পুরনো এবং নতুন কোড একই সময়ে চালিত থাকে (রোলিং ডিপ্লয়, একাধিক ইনস্ট্যান্স, ব্যাকগ্রাউন্ড জব)। একটি মাইগ্রেশন যা দেখতে ঠিক আছে তাও ওই ভার্সনগুলির একটিকে ভঙ্গ করতে পারে।
সামান্য সাধারণ ব্যর্থতার র্যাশি হল:
এমনকি কোড যখন ঠিক থাকে, রিলিজ ব্লক হয়ে যায় কারণ বাস্তব সমস্যা হলো টাইমিং এবং ভার্সনগুলোর মধ্যকার সামঞ্জস্য।
জিরো-ডাউনটাইম স্কিমা পরিবর্তন এক নিয়মে归়ায়: প্রতিটি মধ্যবর্তী অবস্থা পুরনো এবং নতুন কোড—দুটোর জন্যই নিরাপদ হতে হবে। আপনি ডাটাবেস পরিবর্তন করবেন এমনভাবে যাতে বিদ্যমান রিড এবং রাইট ভাঙে না, এমন কোড শিপ করবেন যা দুটো শেপ সামলাতে পারে, এবং পুরনো পথ তখনই সরাবেন যখন কোনো কিছু তার উপর নির্ভর করে না।
এই অতিরিক্ত প্রচেষ্টা বাস্তব ট্রাফিক, কঠোর SLA, বা অনেক অ্যাপ ইনস্ট্যান্স ও ওয়ার্কার থাকলে উপযুক্ত। একটি ছোট ইন্টার্নাল টুল যেখানে ডাটাবেস শান্ত থাকে সেখানে পরিকল্পিত রক্ষণাবেক্ষণের উইন্ডো সহজ হতে পারে।
ডাটাবেস কাজ থেকে ঘটে যাওয়া অধিকাংশ ইন্সিডেন্ট হয় কারণ অ্যাপ আশা করে ডাটাবেস তাৎক্ষণিকভাবে পরিবর্তিত হবে, কিন্তু ডাটাবেস পরিবর্তন সময় নেয়। expand/contract প্যাটার্ন এই সমস্যাটি ছোট, নিরাপদ ধাপে ভেঙ্গে দেয়।
একটি সংক্ষিপ্ত সময়ের জন্য আপনার সিস্টেম দুই "ডায়ালেক্ট" একসাথে সাপোর্ট করে। আপনি প্রথমে নতুন স্ট্রাকচার পরিচয় করান, পুরনোটা চালু রাখেন, ডেটা ধীরে ধীরে সরান, তারপর পরিশোধন করেন।
প্যাটার্নটি সহজ:
এটি রোলিং ডিপ্লয়ের সঙ্গে সুন্দরভাবে কাজ করে। আপনি যদি ১০টি সার্ভার একটার পর একটা আপডেট করেন, তখন সাময়িকভাবে পুরনো ও নতুন ভার্সন একসাথে চলে। expand/contract একই ডাটাবেসে ঐ ওভারল্যাপে উভয়কেই সামঞ্জস্যপূর্ণ রাখে।
এটি রোলব্যাকও কম ভয়ানক করে। যদি নতুন রিলিজে বাগ থাকে, আপনি অ্যাপ রোলব্যাক করতে পারেন ডাটাবেস রোলব্যাক না করেই, কারণ expand উইন্ডো চলাকালীন পুরনো স্ট্রাকচারগুলো এখনও আছে।
উদাহরণ: আপনি PostgreSQL-এ full_name কে first_name এবং last_name-এ ভাগ করতে চান। আপনি প্রথমে নতুন কলামগুলো যোগ করেন (expand), এমন কোড শিপ করেন যা দুই শেপেই পড়তে ও লিখতে পারে, পুরনো রো ব্যাকফিল করেন, তারপর full_name ড্রপ করেন যখন নিশ্চিত হন কিছুই তার উপর নির্ভর করছে না (contract)।
Expand ফেজটি নতুন অপশন যোগ করার কথা বলে, পুরনো অপশনগুলি সরানোর নয়।
সাধারণ প্রথম পদক্ষেপ হচ্ছে নতুন কলাম যোগ করা। PostgreSQL-এ সাধারণত এটি nullable এবং কোন ডিফল্ট ছাড়া যোগ করাই নিরাপদ। নন-নাল কলাম ডিফল্ট সহ যোগ করলে টেবিল রিরাইট বা ভারী লক ট্রিগার করতে পারে, যা Postgres ভার্সন এবং পরিবর্তনের উপর নির্ভর করে। নিরাপদ ধাপগুলি হলো: nullable যোগ করা, সহনশীল কোড ডিপ্লয় করা, ব্যাকফিল করা, তারপর পরে NOT NULL বাধ্য করা।
ইনডেক্সও সতর্কতার দাবি রাখে। সাধারণ ইনডেক্স তৈরি করলে আপনি প্রত্যাশার তুলনায় বেশি সময় ধরে রাইট ব্লক হতে পারেন। যতক্ষণ সম্ভব concurrent index creation ব্যবহার করুন যাতে রিড ও রাইট অনেকটুকু চালু থাকে। এটা বেশি সময় নেবে, কিন্তু রিলিজ বন্ধ করে দেওয়া লক এড়াতে সাহায্য করবে।
Expand নতুন টেবিল যোগ করাও হতে পারে। যদি আপনি একক কলাম থেকে many-to-many রিলেশনশিপে যাচ্ছেন, আপনি একটি join টেবিল যোগ করতে পারেন এবং একই সময়ে পুরনো কলাম বজায় রাখতে পারেন। পুরনো পথ কাজ চালিয়ে যাবে যতক্ষণ নতুন স্ট্রাকচার ডেটা সংগ্রহ শুরু করে।
প্র্যাকটিক্যালি expand প্রায়ই অন্তর্ভুক্ত করে:
Expand শেষ হলে পুরনো এবং নতুন অ্যাপ ভার্সনগুলো অনায়াসে একসাথে চলতে সক্ষম হওয়া উচিত।
অধিকাংশ রিলিজের ব্যথা মাঝখানে ঘটে: কিছু সার্ভার নতুন কোড চলছে, কিছু এখনও পুরনো কোডে, যখন ডাটাবেস ইতিমধ্যেই পরিবর্তনশীল। আপনার লক্ষ্য সরল: রোলআউটের যেকোনো ভার্সনই পুরনো এবং বিস্তৃত—উভয়—স্কিমার সাথে কাজ করবে।
একটি সাধারণ পদ্ধতি হলো dual-write। যদি আপনি একটি নতুন কলাম যোগ করেন, নতুন অ্যাপ উভয়—পুরনো ও নতুন—কলামে লেখে। পুরনো অ্যাপগুলো কেবল পুরনো কলামে লেখাই করবে, যেটা ঠিক আছে কারণ তা এখনও আছে। প্রথমে নতুন কলাম optional রাখুন, এবং কঠোর কনস্ট্রেইন্ট পরে চালু করুন যতক্ষণ না সব লেখক আপগ্রেড হয়।
রিড সাধারণত রাইটের চেয়ে সাবধানে স্যুইচ করা হয়। প্রথমেই পুরনো কলামে রিড রাখতে পারেন (যেটা আপনি জানেন পুরোপুরি ভরা আছে)। ব্যাকফিল ও যাচাইয়ের পরে রিডগুলো নতুন কলামকে প্রাধান্য দেবে, এবং নতুনটি না থাকলে পুরনোতে fallback করবে।
ডাটাবেসের নিচে থাকা অবস্থায়ও আপনার API আউটপুট স্থিতিশীল রাখুন। এমনকি আপনি একটি নতুন অভ্যন্তরীণ ফিল্ড পরিচয় করালেও, সমস্ত কনজিউমার প্রস্তুত না হওয়া পর্যন্ত response shape পরিবর্তন এড়ান (ওয়েব, মোবাইল, ইন্টিগ্রেশন)।
রোলব্যাক-ফ্রেন্ডলি রোলআউট প্রায়শই এমন:
মূল ধারণা হলো প্রথম অপ্রত্যাহার যোগটি হচ্ছে পুরনো স্ট্রাকচারগুলো ড্রপ করা, তাই আপনি এটিকে শেষে পর্যন্ত বিলম্ব করেন।
ব্যাকফিল হচ্ছে যেখানে অনেক "জিরো-ডাউনটাইম" স্কিমা পরিবর্তন ভুল হয়ে যায়। আপনি নতুন কলাম পুরনো রো গুলো ভরতে চান লম্বা লক, ধীর কুয়েরি বা আকস্মিক লোড স্পাইক ছাড়া।
ব্যাচিং গুরুত্বপূর্ণ। এমন ব্যাচ লক্ষ্য করুন যা দ্রুত শেষ হবে (সেকেন্ডসে, মিনিটে নয়)। যদি প্রতিটি ব্যাচ ছোট হয়, আপনি জব থামাতে, পুনরায় শুরু করতে এবং টিউন করতে পারবেন রিলিজ ব্লক করা ছাড়াই।
প্রগতি ট্র্যাক করতে স্থিতিশীল কুর্সর ব্যবহার করুন। PostgreSQL-এ সেটি প্রায়শই প্রাইমারি কী। আইডিতে অর্ডারে প্রক্রিয়া করুন এবং শেষ যে id আপনি সম্পন্ন করেছেন তা সংরক্ষণ করুন, অথবা id রেঞ্জে কাজ করুন। এটা জব রিস্টার্ট হলে ব্যয়বহুল ফুল-টেবিল স্ক্যান এড়ায়।
এখানে একটি সহজ প্যাটার্ন:
UPDATE my_table
SET new_col = ...
WHERE new_col IS NULL
AND id > $last_id
ORDER BY id
LIMIT 1000;
আপডেট কন্ডিশনাল রাখুন (উদাহরণস্বরূপ, WHERE new_col IS NULL) যাতে জব idempotent হয়। রিরান শুধু সেই রো গুলো টাচ করে যেগুলো এখনও কাজের প্রয়োজন, যা অপ্রয়োজনীয় রাইট কমায়।
ব্যাকফিল চলাকালীন নতুন ডেটা আসার পরিকল্পনা করুন। সাধারণ আদেশ হচ্ছে:
ভাল একটি ব্যাকফিল ক্লান্তিকর: স্থির, মাপযোগ্য, এবং ডাটাবেস গরম হলে সহজে থামানো যায়।
সবচেয়ে ঝুঁকিপূর্ণ মুহূর্তটি নতুন কলাম যোগ করা নয়। এটা সিদ্ধান্ত নেওয়া যে আপনি এখন এটিতে নির্ভর করতে পারবেন।
Contract-এ যাওয়ার আগে দুটি বিষয় প্রমাণ করুন: নতুন ডেটা সম্পূর্ণ, এবং প্রোডাকশন এটিকে নিরাপদে পড়ছে।
শুরুতে দ্রুত ও পুনরায় চালনাযোগ্য সম্পূর্ণতা চেকগুলো চালান:
আপনি যদি dual-writing করে থাকেন, একটি consistency চেক যোগ করুন যাতে নিঃশব্দ বাগ ধরা যায়। উদাহরণস্বরূপ, প্রতি ঘণ্টায় এমন একটি কুয়েরি চালান যা old_value <> new_value দেখায় এবং যদি ফলাফল শূন্য না হয় তবে এলার্ট করুন। এটি প্রায়ই দ্রুততম উপায় যে কোনো লেখক এখনও কেবল পুরনো কলাম আপডেট করছে কিনা খুঁজে বের করার।
মাইগ্রেশন চলাকালীন প্রোডাকশন সিগন্যাল নজর করুন। যদি কুয়েরি টাইম বা লক ওয়েট spike করে, এমনকি আপনার "নিরাপদ" যাচাই কুয়েরি গুলোই লোড বাড়াচ্ছে হতে পারে। ডিপ্লয়ের ঠিক পরে নতুন কলাম পড়া পথগুলোর জন্য এরর রেট দেখুন।
কতক্ষণ দুটো পথ রাখা উচিত? অন্তত এক পূর্ণ রিলিজ সাইকেল এবং এক ব্যাকফিল রিরান টিকে বাঁচানোর মতো সময়। অনেক দল ১–২ সপ্তাহ রাখে, অথবা যতক্ষণ না তারা নিশ্চিত হয় কোন পুরনো অ্যাপ ভার্সন আর চলছে না।
Contract হল সেই জায়গা যেখানে টিমরা নার্ভাস হয় কারণ এটা প্রতীয়মান হয়ে যায় ফিরে যাওয়ার পথ নেই। যদি expand ঠিকমতো করা হয়, contract বেশিরভাগই ক্লিনআপ এবং আপনি এটিকে ছোট, নিম্ন-ঝুঁকির ধাপে করতে পারবেন।
মুহূর্তটি সাবধানে বেছে নিন। ব্যাকফিল শেষ হবার ঠিক পরে কিছুই ড্রপ করবেন না। অন্তত একটি পূর্ণ রিলিজ সাইকেল দিন যাতে বিলম্বী জব ও এজ কেসগুলো নিজকে প্রদর্শন করতে পারে।
নিরাপদ contract সিকোয়েন্স সাধারণত এমন:
যদি পারেন, contract কে দুই রিলিজে বিভক্ত করুন: একটি যা কোড রেফারেন্স মুছে ফেলে (অতিরিক্ত লগিং সহ), এবং পরে একটি যা ডাটাবেস অবজেক্ট সরায়। এই বিভাজন রোলব্যাক ও ট্রাবলশুটিংকে অনেক সহজ করে।
PostgreSQL-এ এখানে বিশেষ বিষয় রয়েছে। কলাম ড্রপ করা বেশিরভাগই মেটাডাটা পরিবর্তন, কিন্তু এটি সামান্য ACCESS EXCLUSIVE লক নেয়। একটি শান্ত উইন্ডোর পরিকল্পনা করুন এবং মাইগ্রেশন দ্রুত রাখুন। যদি আপনি অতিরিক্ত ইনডেক্স তৈরি করে থাকেন, সেগুলো DROP INDEX CONCURRENTLY দিয়ে মুছতে পছন্দ করুন যাতে রাইট ব্লক না হয় (এটি ট্রান্স্যাকশন ব্লকে চালানো যায় না, তাই আপনার মাইগ্রেশন টুলিং-এ সাপোর্ট থাকতে হবে)।
জিরো-ডাউনটাইম মাইগ্রেশন ব্যর্থ হয় যখন ডাটাবেস এবং অ্যাপ কি অনুমোদিত/অনুমোদিত সে ব্যাপারে একমত না থাকে। প্যাটার্নটি কাজ করে কেবল যদি প্রতিটি মধ্যবর্তী অবস্থা পুরনো কোড ও নতুন কোড—উভয়ের জন্য নিরাপদ হয়।
এই ভুলগুলো প্রায়ই দেখা যায়:
একটি বাস্তবসম্মত দৃশ্য: আপনি API থেকে full_name লিখে দিতে শুরু করেছেন, কিন্তু একটি ব্যাকগ্রাউন্ড জব এখনও কেবল first_name এবং last_name সেট করে। এটি রাতে চলে, এমন রো ইনসার্ট করে যার full_name = NULL, এবং পরে কোড ধরে নেয় full_name সবসময় আছে।
প্রতিটি ধাপকে এমনভাবে দেখুন যেন এটি দিনগুলো চলতে পারে এমন একটি রিলিজ:
একটি পুনরাবৃত্ত চেকলিস্ট আপনাকে এমন কোড শিপ করা থেকে রোধ করে যা কেবল এক ডাটাবেস স্টেটেই কাজ করে।
ডিপ্লয়ের আগে নিশ্চিত করুন ডাটাবেস ইতিমধ্যেই expanded অংশগুলো আছে (নতুন কলাম/টেবিল, ইনডেক্স যা low-lock ভাবে তৈরি করা হয়েছে)। তারপর নিশ্চিত করুন অ্যাপ সহনশীল: এটি পুরনো শেপ, বিস্তৃত শেপ এবং হাফ-ব্যাকফিল অবস্থায় কাজ করবে।
চেকলিস্ট সংক্ষিপ্ত রাখুন:
একটি মাইগ্রেশন তখনই শেষ হয়েছে যখন রিডগুলো নতুন ডেটা ব্যবহার করছে, রাইটগুলো আর পুরনো ডেটা রাখছে না, এবং আপনি ব্যাকফিলটি অন্তত একটি সাধারণ চেক (কাউন্ট বা স্যাম্পলিং) দিয়ে যাচাই করেছেন।
ধরা যাক আপনার PostgreSQL customers টেবিলে একটি phone কলাম আছে যা বিশৃঙ্খল মান রাখে। আপনি এটিকে phone_e164 দিয়ে প্রতিস্থাপন করতে চান, কিন্তু আপনি রিলিজ ব্লক করতে বা অ্যাপ বন্ধ করতে পারবেন না।
একটি পরিষ্কার expand/contract সিকোয়েন্স এমন দেখায়:
phone_e164 nullable হিসেবে যোগ করুন, কোন ডিফল্ট ছাড়াই, এবং কঠোর কনস্ট্রেইন্ট পরে যোগ করবেন না।phone এবং phone_e164-এ লেখা হয়, কিন্তু রিডগুলো phone-এ রাখুন যাতে ব্যবহারকারীর জন্য কিছুই পরিবর্তন না হয়।phone_e164 পড়ে, এবং যদি তা NULL থাকে তবে phone-এ fallback করে।phone_e164 ব্যবহার করছে, fallback সরান, phone ড্রপ করুন, তারপর প্রয়োজন হলে কঠোর কনস্ট্রেইন্ট যোগ করুন।প্রত্যেক ধাপ পিছনে-কম্প্যাটিবল হলে রোলব্যাক সহজ থাকে। যদি রিড স্যুইচ সমস্যা করে, অ্যাপ রোলব্যাক করুন — ডাটাবেসে উভয় কলামই থাকবে। যদি ব্যাকফিল লোড spike করে, জব থামান, ব্যাচ সাইজ কমান এবং পরে চালিয়ে দিন।
টিমের সঙ্গতি রাখার জন্য পরিকল্পনাটি এক জায়গায় ডকুমেন্ট করুন: সঠিক SQL, কোন রিলিজে রিড ফ্লিপ হবে, সম্পন্নতা কীভাবে পরিমাপ করবেন (যেমন phone_e164 এর non-NULL শতাংশ), এবং প্রত্যেক স্টেপের মালিক কে।
Expand/contract তখনই সেরা কাজ করে যখন এটি রুটিনের মতো লাগে। একটি সংক্ষিপ্ত রুনবুক লিখুন যা আপনার টিম প্রতিটি স্কিমা পরিবর্তনের জন্য পুনঃব্যবহার করতে পারে, সম্ভব হলে এক পৃষ্ঠার মত এবং যথেষ্ট নির্দিষ্ট যাতে একটি নতুন সহকর্মী অনুসরণ করতে পারে।
একটি ব্যবহারিক টেমপ্লেট অন্তর্ভুক্ত করবে:
আগে থেকেই মালিকানা ঠিক করুন। "প্রত্যেকে ভাবছিল কেউ অন্য কেউ contract করবে"—এই ভাবেই পুরনো কলাম ও ফিচার ফ্ল্যাগ মাস দু’মাস টিকে যায়।
এven যদি ব্যাকফিল অনলাইন চলে, ট্রাফিক কম থাকা সময়টা বেছে নিন। ব্যাচ ছোট রাখা, DB লোড নজর রাখা এবং ল্যাটেন্সি বেড়ে গেলে দ্রুত বন্ধ করা সহজ হয়।
আপনি যদি Koder.ai (koder.ai) দিয়ে বিল্ড ও ডিপ্লয় করে থাকেন, Planning Mode আপনার ফেজ ও চেকপয়েন্ট ম্যাপ করতে উপকারী হতে পারে। একই সামঞ্জস্য নিয়ম প্রযোজ্য, কিন্তু ধাপগুলো লিখে রাখা আপনাকে সেই বোরিং কিন্তু জরুরি কাজগুলো বাদ না দিতে সাহায্য করবে।
কারণ আপনার ডাটাবেস আপনার অ্যাপের সব চলমান ভার্সন দ্বারা শেয়ার করা হয়। রোলিং ডিপ্লয় এবং ব্যাকগ্রাউন্ড জব চলাকালে পুরনো এবং নতুন কোড একসাথে হতে পারে, এবং যেকোনো মাইগ্রেশন যা নাম পরিবর্তন করে, কলাম বাদ দেয় বা কনস্ট্রেইন্ট যোগ করে তা সেই নির্দিষ্ট স্কিমা স্টেটে না থাকা কোনো ভার্সনকে ভেঙে দিতে পারে।
এটার মানে হলো মাইগ্রেশন এমনভাবে ডিজাইন করা যাতে ডাটাবেসের প্রতিটি মধ্যবর্তী অবস্থা পুরনো এবং নতুন কোড—উভয়ের জন্যই কাজ করে। আপনি প্রথমে নতুন স্ট্রাকচার যোগ করেন, কিছু সময় দুটো পথেই চলান, তারপর কেবল তখনই পুরনো স্ট্রাকচারগুলি অপসারণ করেন যখন আর কিছু তার উপর নির্ভর করে না।
Expand ফেজে আপনি নতুন কলাম, টেবিল বা ইনডেক্স যোগ করেন যাতে বর্তমান অ্যাপের কোনো দরকারী অংশ মুছে না যায়। Contract হচ্ছে ক্লিনআপ ফেজ যেখানে নতুন পথ পুরোপুরি কাজ করার প্রমাণ পেলে পুরনো কলাম, পুরনো রিড/রাইট এবং অস্থায়ী সিঙ্ক লজিক মুছে ফেলা হয়।
শুরুতে nullable ও কোন ডিফল্ট ছাড়া কলাম যোগ করা সাধারণত সবচেয়ে নিরাপদ, কারণ এটি ভারী লক বা টেবিল রিরাইট এড়ায় এবং পুরনো কোড কাজ চালাতে পারে। পরে কোড ডিপ্লয় করে কলাম অনুপস্থিত বা NULL থাকলে তা সামলাতে হবে, ব্যাকফিল ধীরে ধীরে করা হবে, এবং পরে NOT NULL-এর মতো কনস্ট্রেইন্ট কড়া করা হবে।
যখন ট্রানজিশনে নতুন অ্যাপ ভার্সন একইসঙ্গে পুরনো ইনস্ট্যান্স চলতে পারে, তখন নতুন ভার্সন পুরনো ফিল্ড এবং নতুন ফিল্ড—দুটোতেও লেখে। এতে ডেটা কনসিস্টেন্ট থাকে যতক্ষণ না সব লেখক আপগ্রেড হয়।
ছোট ব্যাচে ব্যাকফিল করুন যাতে প্রতিটি ব্যাচ দ্রুত শেষ হয়, এবং প্রতিটি ব্যাচ idempotent রাখুন যাতে পুনরায় চালালে শুধুমাত্র এখনও কাজ করা rows-গুলোই আপডেট হয়। কুয়েরি টাইম, লক ওয়েট এবং রিপ্লিকেশন ল্যাগ দেখুন এবং ডাটাবেস গরম হলে জব থামাতে বা ব্যাচ সাইজ কমাতে প্রস্তুত থাকুন।
প্রথমত, নতুন কলামে কয়টি NULL আছে তা চেক করে সম্পূর্ণতার প্রমাণ পান। তারপর নমুনা বা কস্ট-সস্তা কনসিস্টেন্সি চেক চালান যা পুরানো ও নতুন মান মিলছে কিনা দেখায়। ডিপ্লয়ের ঠিক পরে প্রোডাকশন এরর দেখুন যাতে কোন কোড-পাথ ভুল স্কিমা ব্যবহার করছে কিনা ধরা যায়।
NOT NULL বা নতুন কনস্ট্রেইন্ট খুব তাড়াতাড়ি যোগ করা, বড় টেবিল এক ট্রানজাকশনে ব্যাকফিল করা, ডিফল্টকে বিনামূল্যে ধরে নেওয়া (কিছু ডিফল্ট table rewrite ট্রিগার করে), এবং রিডগুলো নতুন কলামে স্যুইচ করা আগে যখন রাইটস এখনও ভর্তি করছে না—এইগুলো সাধারণ ভুল।
আপনি কেবল তখনই পুরনো কলাম ড্রপ করবেন যখন পুরনো ফিল্ডে আর লেখা হচ্ছে না, রিডগুলো নতুন ফিল্ডে স্থায়ীভাবে স্যুইচ করেছে এবং দীর্ঘ genug সময় অপেক্ষা করেছেন যাতে নিশ্চিত হওয়া যায় কোনো পুরনো অ্যাপ ভার্সন বা ওয়ার্কার আর চালু নেই। অনেক দল এটা আলাদা রিলিজ হিসেবে দেখে যাতে রোলব্যাক সহজ থাকে।
যদি আপনি একটি রক্ষণাবেক্ষণের উইন্ডো সহ মাইগ্রেশন মেনে নিতে পারেন এবং ট্রাফিক কম থাকে তবে এক-চোখে মাইগ্রেশনও ঠিক আছে। কিন্তু যদি বাস্তব ব্যবহারকারী, বহু অ্যাপ ইনস্ট্যান্স, ব্যাকগ্রাউন্ড ওয়ার্কার বা SLA থাকে, তাহলে expand/contract সাধারণত অতিরিক্ত ধাপগুলোর মূল্য রাখে। Koder.ai Planning Mode-এ ধাপগুলো আগে থেকে লিখে রাখা আপনাকে ‘বোরিং’ ধাপগুলো বাদ না দিতে সাহায্য করবে।