ভার্টিক্যাল স্কেলিং সাধারণত শুধু CPU/RAM যোগ করা। হরাইজন্টাল স্কেলিং সমন্বয়, পার্টিশনিং, কনসিস্টেন্সি ও বেশি অপারেশনাল কাজ চাই—এগুলোই এটিকে কঠিন করে তোলে।

স্কেলিং মানে "আরও সামলাতে পারা, পতন না করে।" সেই "আরও" হতে পারে:
লোকেরা যখন স্কেলিং নিয়ে কথা বলে, তারা সাধারণত এগুলোর এক বা একাধিক উন্নত করার চেষ্টা করে:
এগুলোর বেশিরভাগই একটি থিমে পড়ে: স্কেল আপ করলে ‘একক সিস্টেম’ এর অনুভূতি থাকে, আর স্কেল আউট করলে আপনার সিস্টেম অনেক স্বাধীন মেশিনের সমন্বিত গ্রুপে পরিণত হয়—এবং সেই সমন্বয়ই যেখানে জটিলতা বহুগুণ বেড়ে যায়।
ভার্টিক্যাল স্কেলিং মানে একটি মেশিনকে শক্তিশালী করা। আপনি একই আর্কিটেকচার রাখেন, কিন্তু সার্ভার (বা VM) আপগ্রেড করেন: বেশি CPU কোর, বেশি RAM, দ্রুত ডিস্ক, উচ্চ নেটওয়ার্ক থ্রুপুট।
এটাকে ভাবুন বড় একটা ট্রাক কেনার মতো: এখনও এক ড্রাইভার আর একটা যান, শুধু বেশি মাল বহন করে।
হরাইজন্টাল স্কেলিং মানে আরও মেশিন বা ইনস্ট্যান্স যোগ করে কাজ ভাগ করা—কমনলি লোড ব্যালান্সারের পেছনে। একটিভল একটি শক্তিশালী সার্ভারের বদলে, আপনি একাধিক সার্ভার চালান যেগুলো একসাথে কাজ করে।
এটা অনেক ট্রাক ব্যবহার করার মতো: মোট মাল বেশি নেবেন, কিন্তু এখন শিডিউলিং, রাউটিং ও সমন্বয় নিয়ে চিন্তা করতে হবে।
সাধারণ ট্রিগারগুলো:
টিমগুলো সাধারণত প্রথমে স্কেল আপ করে কারণ তা দ্রুত (বক্স আপগ্রেড)। তারপর যখন একক মেশিন সীমা ছাড়িয়ে যায় বা উচ্চ অ্যাভেইলেবিলিটি দরকার হয় তখন স্কেল আউট করে। পরিপক্ক আর্কিটেকচারে সাধারণত বড় নোড এবং আরও নোড মিশ্রভাবে থাকে, যা বটলনেক অনুসারে নির্ধারিত।
ভার্টিক্যাল স্কেলিং আকর্ষণীয় কারণ এটি আপনার সিস্টেমকে এক জায়গায় রাখে। একক নোড থাকলে সাধারণত মেমরি ও লোকাল স্টেটের একটি একক সোর্স থাকে। একটি প্রসেস ইন-মেমরি ক্যাশ, জব কিউ, সেশন স্টোর (যদি সেশন ইন-মেমরিতে থাকে), এবং টেম্প ফাইলগুলোতে মালিকানা রাখে।
একটি সার্ভারে বেশিরভাগ অপারেশন সরল কারণ নোড-টুও-নোড সমন্বয় ন্যূনঃস্তরে থাকে:
স্কেল আপ করলে আপনি পরিচিত লিভার টানেন: CPU/RAM বাড়ানো, দ্রুত স্টোরেজ ব্যবহার, ইনডেক্স উন্নত করা, কুয়েরি ও কনফিগারেশন টিউন করা। ডেটা কীভাবে বিতরণ হবে বা একাধিক নোড কীভাবে “পরবর্তী কী হবে” নিয়ে একমত হবে তা পুনরায় ডিজাইন করতে হয় না।
ভার্টিক্যাল স্কেলিং "ফ্রি" নয়—কিন্তু জটিলতা সীমাবদ্ধ রাখে।
অবশেষে সীমা আসে: আপনি যে বৃহত্তম ইনস্ট্যান্স ভাড়া নিতে পারেন, diminishing returns, বা উচ্চ প্রান্তে খরচের তীব্র বক্ররেখা। আপনি বেশি ডাউনটাইম ঝুঁকি রাখতে পারেন: যদি এক বড় মেশিন ব্যর্থ হয় বা রক্ষণাবেক্ষণ দরকার হয়, সিস্টেমের বড় অংশ না থাকলে বড় প্রভাব পড়ে—অন্তত যদি আপনি রিডানডেন্সি না রাখেন।
যখন আপনি স্কেল আউট করেন, আপনি কেবল "আরও সার্ভার" পায় না। আপনি আরও স্বাধীন অভিনেতা পান যাদের প্রতি কাজের টুকরা, কোনো সময় এবং কোন ডেটা দিয়ে সিদ্ধান্ত নিতে একমত হতে হবে।
একটি মেশিনে সমন্বয় প্রায়ই ইম্প্লিসিট: এক মেমরি স্পেস, এক প্রসেস, স্টেট দেখার এক জায়গা। অনেক মেশিনে সমন্বয় এমন একটি ফিচার হয়ে যায় যা আপনাকে ডিজাইন করতে হবে।
সাধারণ টুল ও প্যাটার্ন:
সমন্বয় বাগগুলো সাধারণত পরিষ্কার ক্র্যাশের মতো দেখায় না। অধিকাংশ সময় আপনি দেখেন:
এসব সমস্যা সাধারণত ঠিক লোডে, ডেপ্লয়মেন্টের সময়, বা আংশিক ব্যর্থতার সময়ই উঠে আসে। সিস্টেম ঠিক আছে বলে মনে হয়—যতক্ষণ না এটি চাপের মধ্যে আসে।
স্কেল আউট করলে প্রায়ই আপনি সব ডেটা এক জায়গায় রাখতে পারবেন না। আপনি এটাকে মেশিনগুলিতে ভাগ করেন (শার্ড) যাতে একাধিক নোড সমান্তরালে স্টোর ও সার্ভ করতে পারে। সেই ভাগটাই জটিলতার সূচনা: প্রতিটি রিড ও রাইট নির্ভর করে "এটি কোন শার্ডে আছে?"
রেঞ্জ পার্টিশনিং অর্ডার্ড কি দ্বারা ডেটা গ্রুপ করে (যেমন ইউজার A–F শার্ড 1, G–M শার্ড 2)। এতে রেঞ্জ কুয়ারির সহায়তা ভালো। দুর্বল দিক: অনিয়মিত লোড—কোনো একটি রেঞ্জ জনপ্রিয় হলে সেই শার্ড বটলনেক হয়ে যায়।
হ্যাশ পার্টিশনিং একটি কীকে হ্যাশ ফাংশনের মধ্য দিয়ে চালায় এবং শার্ডগুলোর মধ্যে ফলাফল বিতরণ করে। এটা ট্র্যাফিক সমানভাবে ছড়ায়, কিন্তু রেঞ্জ কুয়েরিকে কঠিন করে কারণ সম্পর্কিত রেকর্ডগুলো ছড়িয়ে পড়ে।
নোড যোগ করলে আপনি তা ব্যবহার করতে চান—এর মানে কিছু ডেটা সরাতে হবে। নোড অপসারণ করলে (পরিকল্পিত বা ব্যর্থতায়) অন্য শার্ডগুলো ভূমিকাগুলো গ্রহণ করবে। রিব্যালান্সিং বড় ট্রান্সফার, ক্যাশ ওয়ার্ম-আপ, এবং সাময়িক পারফরম্যান্স ড্রপ ট্রিগার করতে পারে। চলাকালীন আপনাকে ষ্টেইল রিড এবং মিসরুটেড রাইট রোধ করতে হবে।
হ্যাশ থাকলেও বাস্তব ট্র্যাফিক ইউনিফর্ম না। একটি সেলিব্রিটি অ্যাকাউন্ট, জনপ্রিয় প্রোডাক্ট, বা সময়ভিত্তিক প্রবণতা এক শার্ডে পড়তে পারে। একটি হট শার্ড পুরো সিস্টেমের থ্রুপুট কেটে দিতে পারে।
শার্ডিং ধারাবাহিক দায়িত্ব বাড়ায়: রাউটিং নিয়ম বজায় রাখা, মাইগ্রেশন চালানো, স্কিমা পরিবর্তনের পরে ব্যাকফিল করা, ও ক্লায়েন্ট ভেঙে যাওয়া ছাড়া স্প্লিট/মার্জ পরিকল্পনা করা।
স্কেল আউট করলে আপনি কেবল সার্ভার বাড়ান না—আপনি অ্যাপ্লিকেশনের অনুলিপি বাড়ান। কঠিন অংশ হল স্টেট: আপনার অ্যাপ যা অনুরোধের মধ্যে বা কাজ চলাকালীন “মনে রাখে”।
এক ইউজার সার্ভার A তে লগইন করলে তার পরের অনুরোধ সার্ভার B-তে গেলে, কি B জানে তারা কে?
ক্যাশ কাজকে দ্রুত করে, কিন্তু বহু সার্ভার মানে বহু ক্যাশ। এখন আপনাকে মোকাবিলা করতে হয়:
বহু ওয়ার্কার থাকলে ব্যাকগ্রাউন্ড জব দু'বার হতে পারে যদি আপনি এটির জন্য ডিজাইন না করেন। সাধারণত দরকার হয় কিউ, লিজ/লক, বা আইডাম্পটেন্ট জব লজিক যাতে “চালান ইনভয়েস” বা “চার্জ কার্ড” দুবার না ঘটে—বিশেষত রিট্রাই ও রিস্টার্টে।
একটি একক নোড (বা একক প্রাইমারি DB) থাকলে সাধারণত একটি স্পষ্ট "সত্যের সূত্র" থাকে। স্কেল আউট করলে ডেটা ও অনুরোধ মেশিন জুড়ে ছড়ায়, এবং সবাইকে সঙ্গত রাখতে থাকা একটি স্থায়ী উদ্বেগ হয়ে ওঠে।
স্কেল-এ ইভেন্টুয়াল দ্রুত ও সস্তা হতে পারে, কিন্তু এটি সন্তপ্তএজ কেস নিয়ে আসে।
সাধারণ সমস্যা:
ব্যর্থতা মুছে ফেলতে পারবেন না, কিন্তু ডিজাইন করে ক্ষতি কমানো যায়:
সার্ভিস জুড়ে একটি ট্রানজ্যাকশন (অর্ডার + ইনভেন্টরি + পেমেন্ট) বহু সিস্টেমের সম্মতি চায়। যদি একটি ধাপ মাঝপথে ব্যর্থ হয়, আপনাকে ক্ষতিপূরণমূলক অ্যাকশান নেবেন ও সতর্ক হিসাব রাখতে হবে। ক্লাসিক “সব অথবা কিছুই নয়” আচরণ নেটওয়ার্ক ও নোড স্বাধীনভাবে ব্যর্থ হলে কঠিন।
যেগুলো সঠিক থাকতে হবে: পেমেন্ট, অ্যাকাউন্ট ব্যালান্স, ইনভেন্টরি কাউন্ট, সিট রিজার্ভেশন—এইগুলোর জন্য স্ট্রং কনসিস্টেন্সি ব্যবহার করুন। কম ক্রিটিক্যাল ডেটার (অ্যানালিটিক্স, রেকমেন্ডেশন) জন্য ইভেন্টুয়াল কনসিস্টেন্সি গ্রহণযোগ্য।
স্কেল আপ করলে অনেক কল একই প্রসেসে ফাংশন কল—দ্রুত ও পূর্বানুমেয়। স্কেল আউট করলে একই ইন্টারঅ্যাকশন নেটওয়ার্ক কলে পরিণত হয়—ল্যাটেন্সি, জিটার, ও ব্যর্থতা মোড যোগ হয় যেগুলো কোডকে হ্যান্ডেল করতে হবে।
নেটওয়ার্ক কলের ফিক্সড ওভারহেড (সিরিয়ালাইজেশন, কিউয়িং, হপ) এবং ভেরিয়েবল ওভারহেড (কনজেশন, রাউটিং, noisy neighbors) থাকে। গড় ল্যাটেন্সি ঠিক থাকলেও টেইল ল্যাটেন্সি (সবচেয়ে ধীর 1–5%) ইউজার অভিজ্ঞতাকে কাবু করতে পারে কারণ একটি ধীর নির্ভরতা পুরো রিকোয়েস্টটিকে থামিয়ে দেয়।
ব্যান্ডউইথ ও প্যাকেট লসও সীমানা হয়ে দাঁড়ায়: উচ্চ রেটেতে ছোট পে-লোডগুলো জমা হয় এবং রিট্রান্সমিটগুলো নীরবে লোড বাড়ায়।
টাইমআউট ছাড়া ধীর কল জমে থ্রেড আটকে রাখে। টাইমআউট ও রিট্রাই দিয়ে আপনি রিকভার করতে পারেন—যদি না রিট্রাই লোডকে বাড়িয়ে দেয়।
একটি সাধারণ ব্যর্থতা প্যাটার্ন: একটি ব্যাকএন্ড ধীর হয়ে যায় → ক্লায়েন্ট টাইমআউট করে ও রিট্রাই করে → রিট্রাই লোড বাড়ায় → ব্যাকএন্ড আরও ধীর হয়।
নিরাপদ রিট্রাই সাধারণত:
বহু ইনস্ট্যান্সে ক্লায়েন্টদের কোথায় অনুরোধ পাঠাতে হবে তা জানতে হয়—লোড ব্যালান্সার বা সার্ভিস ডিসকভারি + ক্লায়েন্ট-সাইড ব্যালান্সিং। যেকোন পদ্ধতিই আরো চলমান অংশ যোগ করে: হেলথ চেক, কানেকশন ড্রেনিং, অসম ট্র্যাফিক ডিস্ট্রিবিউশন, এবং আংশিক ভাবে বিকল ইনস্ট্যান্সে রাউট করার ঝুঁকি।
ওভারলোড ছড়িয়ে পড়া থামাতে ব্যাকপ্রেশার দরকার: বাউন্ডেড কিউ, সার্কিট ব্রেকার, রেট লিমিটিং। উদ্দেশ্য হলো দ্রুত ও পূর্বানুমেয়ভাবে ফেইল করা, যাতে একটি ছোট ধীরতা সিস্টেম-ব্যাপী ইনসিডেন্টে পরিণত না হয়।
ভার্টিক্যাল স্কেলিংতে ব্যর্থতা সহজভাবে ঘটে: একটি বড় মেশিন এখনও সিংগল পয়েন্ট। এটি ধীর বা ক্র্যাশ করলে প্রভাব স্পষ্ট।
স্কেল আউটে গাণিতিক পরিবর্তন হয়। বহু নোড থাকলে কিছু মেশিন অসুস্থ থাকা স্বাভাবিক, অন্যগুলো ঠিক থাকবে। সিস্টেম "আপ" কিন্তু ব্যবহারকারীরা ত্রুটি, ধীর পৃষ্ঠা বা অসঙ্গত আচরণ দেখতে পারে। এটি আংশিক ব্যর্থতা, এবং এটি সেই ডিফল্ট অবস্থা যার জন্য আপনাকে ডিজাইন করতে হয়।
স্কেল-আউট সেটাপে সার্ভিসগুলো অন্য সার্ভিসের ওপর নির্ভরশীল: DB, ক্যাশ, কিউ, ডাউনস্ট্রীম API। একটি ছোট সমস্যা রেপলিং করে:
বাঁচার জন্য সিস্টেম রিডানডেন্সি বাড়ায়:
এগুলো অ্যাভেইলেবিলিটি বাড়ায়, কিন্তু এজ-কেস নিয়ে আসে: স্প্লিট-ব্রেইন, স্টেল রেপ্লিকা, কোয়োরাম না হলে কী করা হবে—এসব সিদ্ধান্ত নেওয়া লাগবে।
সাধারণ প্যাটার্ন:
একটি একক মেশিনে সিস্টেম কাহিনী এক জায়গায়: একটি লগ সেট, একটি CPU গ্রাফ, একটি প্রসেস। হরাইজন্টাল স্কেলে কাহিনী ছড়িয়ে পড়ে।
প্রতিটি নোড একটি লগ, মেট্রিক, ট্রেস স্ট্রিম যোগ করে। কঠিন অংশটি ডেটা সংগ্রহ নয়—এগুলোকে কোরিলেট করা। একটি চেকআউট ত্রুটি ওয়েব নোড থেকে শুরু করে দুইটি সার্ভিস, একটি ক্যাশ ও একটি নির্দিষ্ট শার্ডে পড়তে পারে—উভয় জায়গায় ও সময়রেখায় আলাদা ক্লুয থাকে।
সমস্যাও নির্বাচনী হতে পারে: একটি নোডে খারাপ কনফিগ, একটি শার্ডে হটনেস, একটি জোনে উচ্চ ল্যাটেন্সি। ডিবাগিং র্যান্ডম মনে হতে পারে কারণ বেশিরভাগ সময় এটা ঠিক থাকে।
ডিস্ট্রিবিউটেড ট্রেসিং মানে একটি রিকোয়েস্টকে ট্র্যাকিং নম্বর দেওয়ার মতো। কোরিলেশন আইডি সেই নম্বর। আপনি এটাকে সার্ভিস জুড়ে পাঠান এবং লগে রাখেন যাতে একটি ID দেখে আপনি শেষ পর্যন্ত পুরো যাত্রা দেখতে পারেন।
বেশি কম্পোনেন্ট মানে বেশি অ্যালার্ট। টিউন না করলে টিম অ্যালার্ট ফ্যাটিগued হবে। লক্ষ্যমুখী অ্যালার্ট করুন যা পরিষ্কার বলে:
ক্যাপাসিটি ইস্যু প্রায়ই ব্যর্থতার আগে দেখা যায়। CPU, মেমরি, কিউ গভীরতা, কানেকশন পুল ব্যবহারের মতো স্যাচুরেশন সিগন্যাল মনিটর করুন। যদি স্যাচুরেশন কেবল নির্দিষ্ট একটি নোডে দেখা যায়, তাহলে ব্যালান্সিং, শার্ডিং, বা কনফিগ ড্রিফট সন্দেহ করুন—শুধু "আরও ট্র্যাফিক" নয়।
স্কেল আউট হলে ডেপ্লয় আর শুধু "একটা বক্স বদলানো" নয়। এটি বহু মেশিন জুড়ে পরিবর্তন সমন্বয় করা যাতে সার্ভিস উপলব্ধ থাকে।
হরাইজন্টাল ডেপ্লয়মেন্ট প্রায়ই রোলিং আপডেট (ধীরে ধীরে নোড বদলানো), ক্যানারি (কম অংশ ট্র্যাফিক পাঠানো নতুন ভার্সনে), বা ব্লু/গ্রিন (দুই পুরো পরিবেশের মধ্যে ট্র্যাফিক সুইচ) ব্যবহার করে। এগুলো ব্লাস্ট রেডিয়াস কমায়, কিন্তু চাহিদা বাড়ায়: ট্র্যাফিক শিফটিং, হেলথ চেক, কানেকশন ড্রেনিং, এবং "চলমান পর্যাপ্ত"-এর সংজ্ঞা থাকা দরকার।
যেকোন ধাপে পুরনো ও নতুন ভার্সন পাশাপাশি চলবে। ভার্সন স্কিউ মানে সিস্টেমকে মিক্সড আচরণ সহ্য করতে হবে:
API-কে ব্যাকওয়ার্ড/ফরওয়ার্ড কম্প্যাটিবল রাখতে হবে। DB স্কিমা পরিবর্তন সাধারণত অ্যাডিটিভ হওয়া উচিত (প্রথমে nullable কলাম যোগ করা, পরে required করা)। মেসেজ ফরম্যাট ভার্সনিং করা দরকার যাতে কনজিউমার উভয় পুরনো ও নতুন ইভেন্ট পড়তে পারে।
কোড রোলব্যাক সহজ; ডেটা রোলব্যাক নয়। যদি মাইগ্রেশন ফিল্ড ড্রপ বা রিপ্লেস করে, পুরনো কোড ক্র্যাশ করতে পারে বা রেকর্ডগুলো ভুলভাবে হ্যান্ডেল করতে পারে। "এক্সপ্যান্ড/কন্ট্রাক্ট" মাইগ্রেশন প্যাটার্ন সাহায্য করে: এমন কোড ডেপ্লয় করুন যা দুটো স্কিমা সাপোর্ট করে, ডেটা মাইগ্রেট করুন, পরে পুরনো পথ সরান।
বেশি নোড হলে কনফিগ ম্যানেজমেন্ট ডেপ্লয় অংশ হয়ে ওঠে। একটি নোড যদি স্টেইল কনফিগ, ভুল ফিচার ফ্ল্যাগ, বা মেয়াদ উত্তীর্ণ ক্রেডেনশিয়াল রাখে তাহলে ফ্লেকি ও রেপ্রডিউস করা কঠিন ব্যর্থতা সৃষ্টি হতে পারে।
হরাইজন্টাল স্কেলিং কাগজে সস্তা দেখাতে পারে: অনেক ছোট ইনস্ট্যান্স, প্রতিটি কম ঘণ্টার দাম। কিন্তু মোট খরচ কেবল কম্পিউট নয়। নোড বাড়ালে আরও নেটওয়ার্কিং, মনিটরিং, সমন্বয়, এবং মেইনটেন্যান্স লাগবে।
ভার্টিক্যাল স্কেলিং খরচকে কম সংখ্যক হোস্টে কেন্দ্রীভূত করে—কম হোস্ট প্যাচ, কম এজেন্ট, কম লগ শিপিং, কম মেট্রিক স্ক্র্যাপিং।
স্কেল আউটে প্রতিটি ইউনিট কম দামি হতে পারে, কিন্তু সাধারণত আপনি খরচ দেবেন:
স্পাইক নিরাপদভাবে হ্যান্ডেল করতে বিতরিত সিস্টেম প্রায়ই আন্ডার-ফুল চলে। ওয়েব, ওয়ার্কার, DB, ক্যাশ—প্রতিটি স্তরে হেডরুম রাখতে হয়, যার মানে ডজন বা শত শত ইনস্ট্যান্সে পদবেকভাবে খরচ হয়।
স্কেল আউট অন-কল লোড বাড়ায় এবং পরিপক্ক টুলিং দাবি করে: অ্যালার্ট টিউনিং, রুনবুক, ইনসিডেন্ট ড্রিল, ট্রেনিং। টিমগুলো দায়িত্বের সীমা (কে কোন সার্ভিস ম্যানেজ করে?) ও ইনসিডেন্ট সমন্বয়ে সময় ব্যয় করে।
ফলে: "প্রতি ইউনিট সস্তা" হওয়া সত্ত্বেও মানুষ-ঘন্টার এবং অপারেশনাল ঝুঁকি যোগ করলে মোট মিলিয়ে বেশি ব্যয় বহন করতে হতে পারে।
স্কেল আপ বনাম স্কেল আউট বেছে নেওয়া কেবল দাম নয়। এটি ওয়ার্কলোড শেইপ ও আপনার টিম কতটা অপারেশনাল জটিলতা সহ্য করতে পারে তাও বিবেচ্য।
ওয়ার্কলোড থেকে শুরু করুন:
একটা সাধারণ, যুক্তিসঙ্গত পথ:
অনেক টিম ডেটাবেসকে ভার্টিক্যাল (বা হালকা ক্লাস্টার) রেখে স্ট্যাটলেস অ্যাপ টিয়ার হরাইজন্টাল করে। এতে শার্ডিং ব্যথা কমে আর ওয়েব ক্যাপাসিটি দ্রুত যোগ করা যায়।
আপনি কাছে আছেন যখন আপনার কাছে শক্ত মনিটরিং ও অ্যালার্ট, টেস্টেড ফেইলোভার, লোড টেস্ট, এবং রোলব্যাক সহ পুনরাবৃত্ত ডেপ্লয়মেন্ট আছে।
স্কেল আপ দ্রুত ও কম জটিলভাবে কাজ বাড়ায়, কিন্তু সীমাবদ্ধতা ও একক পয়েন্টের ঝুঁকি থাকে। স্কেল আউট বড় স্কেল ও উচ্চ উপলব্ধি দেয়, কিন্তু এটি সমন্বয়, পার্টিশনিং, কনসিস্টেন্সি, নেটওয়ার্কিং এবং অপারেশনাল ও টিম জটিলতা যোগ করে।
সঠিক পথ নির্ভর করে কাজের প্রকৃতি, বৃদ্ধির ধরন, এবং আপনার টিম কতটা অপারেশনাল দায়িত্ব নেওয়ার জন্য প্রস্তুত—সুতরাং প্রথমে অপটিমাইজ করুন, প্রয়োজনে স্কেল আপ করুন, এবং যখন একক নোড সীমা ছাড়ায় বা উচ্চ অ্যাভেইলেবিলিটি দরকার তখন স্কেল আউট বিবেচনা করুন।
ভার্টিক্যাল স্কেলিং মানে একটি একক মেশিনকে বড় করা (আরও CPU/RAM/দ্রুত ডিস্ক)। হরাইজন্টাল স্কেলিং মানে আরও মেশিন যোগ করে কাজ ছড়িয়ে দেওয়া।
ভার্টিক্যাল সাধারণত সহজ মনে হয় কারণ আপনার অ্যাপ এখনও "একটি সিস্টেম" এর মতো আচরণ করে, আর হরাইজন্টাল হলে অনেক সিস্টেমকে সমন্বয় রাখতে হয় এবং সঙ্গতি বজায় রাখতে extra কাজ করতে হয়।
একবার আপনার কাছে বহু নোড থাকলে আপনাকে স্পষ্টভাবে সমন্বয় করতে হবে:
একটি একক মেশিন অনেক বিতরণকৃত সিস্টেম সমস্যা স্বয়ংক্রিয়ভাবে এড়িয়ে দেয়।
এটা হলো এতগুলো মেশিনকে এক হিসাবে আচরণ করাতে ব্যয়—সময় এবং লজিক:
প্রতিটি নোড সহজ হলেও, পুরো এবং ব্যর্থতার অধীনে পুরো সিস্টেমের আচরণ বোঝা কঠিন হয়ে ওঠে।
শার্ডিং ডেটাকে নোডে ভাগ করে তাই কোনো এক মেশিন সব কিছু রাখতে বা সার্ভ করতে হয় না। কঠিন হওয়ার কারণগুলো:
এটা অপারেশনাল কাজও বাড়ায় (মাইগ্রেশন, ব্যাকফিল, শার্ড ম্যাপ মেইনটেন্যান্স)।
স্টেট হল এমন কিছু যা আপনার অ্যাপ অনুরোধগুলোর মধ্যে বা কাজ চলাকালীন “মনে রাখে” (সেশন, ইন-মেমরি ক্যাশ, টেম্প ফাইল, জব প্রগ্রেস)।
হরাইজন্টাল করলে একই ইউজারের অনুরোধ বিভিন্ন সার্ভারে পড়তে পারে, তাই সাধারণত শেয়ার্ড স্টোর (Redis/DB) লাগে, বা স্টিকি সেশন গ্রহণ করে ধরণগত ট্রেড-অফ মেনে নিতে হয়।
যদি একাধিক ওয়ার্কার একই জব পিক করতে পারে বা রিট্রাই ঘটে, তখন ডুপ্লিকেট কাজ চালানো হতে পারে (দু'বার চার্জ, দ্বৈত ইমেইল)। সাধারণ প্রতিকার:
স্ট্রং কনসিস্টেন্সি মানে লেখার পরে সব পাঠক তৎক্ষণাৎ সর্বশেষ মান দেখবে। ইভেন্টুয়াল কনসিস্টেন্সি মানে আপডেটগুলো সময়ের সাথে ছড়াবে, তাই কিছু সময় কিছু পাঠক পুরোনো মান দেখতে পারে।
পেমেন্ট, ব্যালেন্স, ইনভেন্টরি মতো ক্রাইটিক্যাল ডেটার জন্য স্ট্রং কনসিস্টেন্সি দরকার; অ্যানালিটিক্স বা রেকমেন্ডেশনে ইভেন্টুয়াল কনসিস্টেন্সি গ্রহণযোগ্য হতে পারে।
বিতরিত সিস্টেমে কলগুলো নেটওয়ার্ক কল হয়ে যায়—এতে ল্যাটেন্সি, জিটার, এবং নতুন ব্যর্থতা মোড আসে। সাধারণভাবে যা দরকার:
না হলে রিট্রাই স্টর্ম তৈরি হতে পারে যা ব্যাকএন্ডকে আরও ধীর করে দেয়।
পার্শিয়াল ফেইলিওর মানে কিছু কম্পোনেন্ট ভাঙা বা ধীর অথচ অন্যগুলো ঠিক আছে—সিস্টেম "আপ" থাকতে পারে কিন্তু তবুও ত্রুটি বা স্লো দেখতে পাওয়া যায়।
পারে এলিমেন্টস: রেপ্লিকেশন, কোয়োরাম, মাল্টি-জোন ডেপ্লয়মেন্ট, সার্কিট ব্রেকার, গ্রেসফুল ডিগ্রেডেশন—কিন্তু এগুলোও নতুন সীমানা ও এজ-কেস দেয় (স্প্লিট-ব্রেইন, স্টেল রেপ্লিকা ইত্যাদি)।
অনেক সার্ভারে চললে ইভিডেন্স টুকরো টুকরো হয়: লগ, মেট্রিক, ট্রেস বিভিন্ন জায়গায়। করণীয়:
এগুলো ডিবাগিংকে কার্যকর করে।
স্কেল-আউট হলে ডেপ্লয় একটি বহু-নোড সমন্বয়; কৌশলগুলো:
কনফিগ ও সিক্রেটস কনসিস্টেন্ট রাখা জরুরি; নইলে স্টেইলের কারণে বেকফায়ার দেখা দিতে পারে।
অনেক ছোট ইনস্ট্যান্স কাগজে সস্তা দেখাতে পারে, কিন্তু মোট মূল্যের মধ্যে নেটওয়ার্ক, মনিটরিং, অতিরিক্ত রেপ্লিকা এবং অপারেশনাল কাজ যোগ হয়।
অতিরিক্ত খরচ:
ফলে ব্যক্তি-সময় ও অপারেশনাল ঝুঁকি যোগ করলে মোট খরচ বাড়তে পারে।
নির্ধারণ কেবল দাম নয়—ওয়ার্কলোডের ধরন ও আপনার টিমের অপারেশনাল সক্ষমতা গুরুত্বপূর্ণ:
সাধারণ প্র্যাকটিক্যাল ধাপ: অপটিমাইজ → প্রথমে স্কেল-আপ → একবার একক নোডই সীমা হলে বা অ্যাভেইলেবিলিটি চাইলে স্কেল-আউট।
হাইব্রিড প্যাটার্ন খুব সাধারণ: স্ট্যাটলেস অ্যাপ টিয়ার স্কেল-আউট করা হয়, ডেটাবেসকে ভার্টিক্যাল বা হালকা ক্লাস্টার করা হয় যাতে শার্ডিং ব্যথা কম থাকে।
অনেক স্কেলিং ব্যথা হলো অপারেশনাল লুপ: নিরাপদভাবে ইটারেট করা, নির্ভরযোগ্যভাবে ডেপ্লয় করা, দ্রুত রোলব্যাক করা।
Koder.ai আপনাকে দ্রুত প্রোটোটাইপ এবং শিপ করতে সাহায্য করতে পারে, উদাহরণস্বরূপ:
এছাড়া AWS-এ গ্লোবাল রান হওয়ায় বিভিন্ন রিজিয়নে ডেপ্লয় করে ল্যাটেন্সি ও ডেটা ট্রান্সফার কনস্ট্রেইন্ট মিট করতেও সুবিধা হয়।