পর্ব ৪: Valkey, Queue আর Log, যে নীরব অংশগুলো আগে ভাঙে
NovaCommerce কেস স্টাডির চতুর্থ পর্ব: ২,৮৫৪টি Valkey timeout, একমাত্র worker যে এখনও single point of failure, ১১৫ মিনিট পর্যন্ত merit card আটকে রাখা একটি queue, "না" বলা AI provider আর ভবনকে গুনে ফেলা একটি rate limiter।
৬ অক্টোবর ০২:২৮-এ একটি backend load test শেষ হলো ২,৮৫৪টি application error নিয়ে। প্রতিটির বার্তা একই, connect করতে গিয়ে ছুড়ে দেওয়া: RedisException: Operation timed out। web server ঠিক ছিল, database-ও ঠিক ছিল। "না" বলেছিল সেই নীরব সার্ভিসটি, যে session, cache আর queue ধরে রাখে।
একই সপ্তাহে আরেকটি সংখ্যা পেলাম: ১১৫। পরীক্ষার পর সবচেয়ে ধীর merit card-টি recompute হওয়ার জন্য ১১৫ মিনিট অপেক্ষা করেছে। দোষ worker-এর CPU-র ছিল না, WebSocket-এরও না। জবটি শুধু ভুল লাইনে দাঁড়িয়ে ছিল।
পার্ট ৩-এ আমরা database নিয়ে কথা বলেছি। এই পার্টে সেই অংশগুলো, যেগুলো একটি stateless fleet-কে জুড়ে রাখে: Valkey, একমাত্র fixed worker, queue, rate limit, log আর যেসব signal আমরা নজরে রাখি। diagram-এ এগুলো পানসে দেখায়, অথচ আমাদের বাস্তব চমকগুলোর বড় একটা অংশ এসেছে এখান থেকেই। তাই নিচের প্রতিটি অংশ একটি ব্যর্থতা, তার কারণ আর একটি পরিবর্তন।
এটি "From One Server to Exam-Day Ready" নামের পাঁচ পর্বের কেস স্টাডির চতুর্থ পর্ব। NovaCommerce একটি কাল্পনিক নাম; architecture, সংখ্যা আর ভুলগুলো বাস্তব।
যে fleet-এর স্মৃতি নেই, তার মনে রাখার জায়গা লাগে
যে node যেকোনো মিনিটে মুছে ফেলা যায়, সে কিছুরই মালিক হতে পারে না। এই প্ল্যাটফর্মে মালিকদের তালিকা ছোট: application data-র জন্য managed MySQL, AI embedding-এর জন্য pgvector-সহ managed PostgreSQL, ফাইলের জন্য Spaces object storage, log-এর জন্য managed OpenSearch, আর যা কিছু ছোট, দ্রুত ও সবার ভাগের, সেসবের জন্য managed Valkey: session, cache আর queue।
সুপারশপের ক্যাশিয়ারদের কথা ভাবুন। টাকার ড্রয়ার আর স্টকের তালিকা থাকে পেছনের অফিসে। শিফটের মাঝখানে একজন চলে গেলেও পরের জন তার কাউন্টারে বসে পড়ে, কারণ ক্যাশিয়ারের পকেটে কিছুই ছিল না।
ওপরের node-গুলো কিছুই ধরে রাখে না। node মুছে গেলেও যা টিকে থাকতে হবে, তা নিচের পাঁচটি store-এর কোনো একটিতে থাকে।
এটা আমরা ধরে নিইনি, যাচাই করেছি। ৭ অক্টোবর backend node-গুলো ২৪ ঘণ্টায় local disk-এ ০টি ফাইল লিখেছে। upload, এমনকি শিক্ষার্থীদের লিখিত উত্তরের PDF-ও, সোজা Spaces-এ যায়; session ও cache থাকে Valkey-তে; log যায় stdout-এ। Implemented এবং যাচাই করা। এ কারণেই autoscale pool যেকোনো সময় যেকোনো node মুছে ফেলতে পারে।
তথ্য
কোথায় থাকে
আমরা কী পাই
Session
Valkey (primary + standby)
যেকোনো backend node যেকোনো শিক্ষার্থীকে সেবা দিতে পারে
Cache
Valkey
সব node-এর জন্য একটিই cache
Queue-তে থাকা job
Valkey
worker বন্ধ থাকলেও submission নিরাপদে অপেক্ষা করে
Upload, উত্তরের PDF, media
CDN-সহ Spaces
কোনো ফাইল কখনো node-এর disk-এ থাকে না
Log
stdout, সেখান থেকে OpenSearch-এ
node চলে গেলেও টিকে থাকে (backend শেষ, frontend planned)
Application data
Managed MySQL
পার্ট ৩-এ আলোচিত
ইচ্ছা করেই একটি Valkey
cache, session আর queue একই managed Valkey 8-এ থাকে, সঙ্গে একটি standby node। এর eviction policy noeviction: memory ভরে গেলে Valkey পুরোনো key চুপচাপ মুছে না দিয়ে নতুন write-এ error দেয়। শুধু cache হলে এটা উল্টো শোনায়। কিন্তু এই instance-এ session আর queue-তে থাকা job-ও আছে, আর কোনো job চিহ্ন ছাড়া হারিয়ে যাওয়ার চেয়ে আমরা জোরালো error পছন্দ করি। সেই সীমা থেকে আমরা অনেক দূরে: ৭ অক্টোবরের পরীক্ষার সন্ধ্যায় এটি memory-র প্রায় ১২.৫% ব্যবহার করেছে।
২,৮৫৪টি timeout: ভাগের memory যখন আর সাড়া দিতে পারল না
আবার ০২:২৮-এ ফিরি। test-টি আঘাত করছিল ৪ GB-এর একটি Valkey-কে, primary আর standby-সহ। সমস্যা memory-র ছিল না। load-এর মধ্যে সে নতুন connection যথেষ্ট দ্রুত নিতে পারছিল না, আর যে request ৫ সেকেন্ডের connect timeout-এর বেশি অপেক্ষা করেছে, সেটাই ৫০০ হয়েছে।
চাপের একটা অংশ আমাদের নিজেদের তৈরি। প্রতিটি request Valkey-র সঙ্গে নতুন করে একটি TLS connection খুলত, যার খরচ আমরা মেপেছি request প্রতি প্রায় ৫.৪ ms CPU (MySQL-এর জন্য প্রায় ৩.৩ ms)। একটি backend node যে ৬৫ থেকে ৭০ request/s দিতে পারে, সেখানে শুধু এই handshake-ই প্রায় এক core-এর এক-তৃতীয়াংশ খায়। এটা হিসাবের মোটামুটি আন্দাজ, profile নয়।
সমাধান ছিল একটি resize, জায়গায় বসেই: Valkey ৪ GB থেকে ৮ GB, দুটি node (primary ও standby) হলো; data থেকে গেল, host name বদলাল না। application-এ কোনো পরিবর্তন নেই, কোনো cutover নেই। Implemented।
তারপর আবার মাপলাম। Tested: দুটি backend node দিয়ে শুরু করে, pool-কে বাড়তে দিয়ে, ২৫ থেকে ৫০০ request/s পর্যন্ত ধাপে ধাপে বাড়িয়ে পেলাম ০টি application error আর ০টি backend 5xx। load balancer-এ ১৪৩টি error এসেছিল, কিন্তু শুধু তখনই, যখন node-গুলোর CPU পুরো ভরা ছিল: এটাই প্রত্যাশিত "ক্ষমতা শেষ" signal, bug নয়।
এখান থেকে কাজের শিক্ষাটা হলো, কয়েক দিনের মধ্যে bottleneck তিনবার সরেছে, আর প্রতিবার আলাদা ধরনের সমাধান লেগেছে।
ক্রম
Bottleneck
সমস্যার ধরন
সমাধান
১
IP ধরে চলা API rate limiter
Code ও configuration
account ধরে গোনা (Implemented)
২
Valkey connection
Data-tier-এর size
৪ GB থেকে ৮ GB, ২টি node (Implemented)
৩
প্রতি node-এর backend CPU
সরল ক্ষমতার ঘাটতি
আরও node, আগে থেকে pre-scale (Implemented)
শুধু শেষ সারির সমাধান server বাড়িয়ে হয়। দ্বিতীয়টিতে server বাড়ালে একই Valkey-র ওপর আরও বেশি connection পড়ত।
একটি worker, আর যে কাজগুলো শুধু সে-ই করতে পারে
worker-কে ঘিরে সবকিছু scale করে। worker নিজে করে না। এটি একটিই fixed droplet (৪ vCPU, ৮ GB), আর এর কাঁধে চারটি কাজ:
Queue। default, exam, তিনটি notification queue, OMR আর enrollment report, চালায় Horizon।
Scheduler। সময়-নির্ধারিত কাজ ঠিক একবারই চলতে হবে।
WebSocket। live update দেয় Reverb। এর port শুধু tag ধরে backend node-গুলোর জন্য খোলা।
সব SMS। SMS gateway কেবল একটি IP address whitelist করে, তাই SMS শুধু এই মেশিন থেকেই বেরোতে পারে।
এ কারণেই web node-এ queue, scheduler, WebSocket ও OMR বন্ধ রাখা হয়েছে: autoscale-এ আসা নতুন node যেন কখনো একই job দুবার না চালায়। সাধারণ নিয়মের সঙ্গে আমাদের ঘটনা যা যোগ করে, তা হলো SMS বাঁধা একটি address-এর সঙ্গে, শুধু একটি process-এর সঙ্গে নয়।
এটি একটি single point of failure, আর আমরা সোজাসুজি সেটা বলি। এই droplet মরে গেলে SMS, scheduler আর exam processing থেমে যায়। শিক্ষার্থীরা submit করতেই থাকে, আর তাদের submission নিরাপদে Valkey-তে অপেক্ষা করে; queue সেখানে রাখার কারণই এটা। কিন্তু worker ফিরে না আসা পর্যন্ত কেউ সেগুলো process করে না।
৭ অক্টোবরের পরীক্ষার সন্ধ্যায় worker-এর CPU সর্বোচ্চ ৪৬% ছুঁয়েছে, failed job ০টি; অর্থাৎ এটি এমন ঝুঁকি, যার জন্য আমরা পরিকল্পনা করছি, এমন ব্যর্থতা নয় যা আমরা দেখেছি। পরিকল্পনাটি সৎ label-সহ:
ধাপ
কেন
অবস্থা
Reserved IP, SMS gateway-তে whitelist করা
বদলি worker চেনা address থেকে SMS পাঠাতে পারে
Planned
ছোট একটি standby worker
queue আর scheduler নিতে প্রস্তুত একটি মেশিন
Planned
শুধু পরীক্ষার জন্য burst worker image, বড় পরীক্ষার আগে চালু করা
যখন দরকার, তখন বাড়তি queue ক্ষমতা
Planned
worker-এর একটি snapshot
rebuild শুরু হয় image থেকে, স্মৃতি থেকে নয়
Implemented
Reserved IP আগে আসে: এটা ছাড়া standby worker এমন address থেকে SMS পাঠাত, যা gateway গ্রহণ করে না।
১১৫ মিনিট অপেক্ষা করা merit card
পরীক্ষার পর একটি "merit recompute" job প্রতিটি শিক্ষার্থীর merit card নতুন করে হিসাব করে। ৬ অক্টোবর সেই card-গুলো আসছিল ১০ থেকে ১১৫ মিনিট দেরিতে।
যা আমরা বাদ দিয়েছিলাম
প্রথম সন্দেহ ছিল worker-এর CPU আর WebSocket server। কোনোটাই কারণ নয়।
আসল কারণ
merit job খুবই ছোট: ০.৩৪ সেকেন্ড। কিন্তু সে একটি queue ভাগ করছিল, যার ২টি worker, এমন একটি AI job-এর সঙ্গে, যেটা প্রতি শিক্ষার্থীর জন্য প্রায় ১০ সেকেন্ডের একটি language-model call করে। পরীক্ষার পর প্রায় ২,০০০টি এমন AI job enqueue হলো, আর প্রতিটি merit job তাদের পেছনে পড়ে গেল।
হিসাবটা মাপ বুঝিয়ে দেয়। একটি AI job-এর সময়ে প্রায় ২৯টি merit job শেষ হয়ে যায়। দুই হাজারটি মানে প্রায় ২০,০০০ সেকেন্ডের কাজ, আর ২টি worker-এ ভাগ করলে প্রায় তিন ঘণ্টার লাইন। ১০ থেকে ১১৫ মিনিটের অপেক্ষা এই ছবির সঙ্গে মেলে।
এটা সুপারশপের express lane-এর গল্প: এক প্যাকেট রুটি ভরা ট্রলির পেছনে দাঁড়ানোর কথা নয়, অথচ আমরা সবার জন্য একটিই কাউন্টার বানিয়ে রেখেছিলাম।
একই job, ভিন্ন topology: ডানে merit job কখনো AI job-এর মুখোমুখি হয় না, আর AI lane-এর নিজের গতি আছে।
পরিবর্তন
Implemented: শুধু AI narrative-এর জন্য আলাদা একটি queue lane আর নিজস্ব container, ২টি replica-সহ। merit ও position job আর কখনো language model-এর জন্য অপেক্ষা করে না, আর merit card এখন প্রায় এক মিনিটে তৈরি হয়। আগে থেকে অপেক্ষায় থাকা AI job-গুলো একটি atomic script দিয়ে নতুন lane-এ সরানো হয়েছে, যাতে প্রতিটি job প্রতি মুহূর্তে ঠিক এক জায়গায় থাকে।
সমাধানটা ছিল topology, বাড়তি শক্তি নয়। ধরনভেদে আলাদা queue রাখার সাধারণ নিয়মটি আছে Queues and Workers at Scale-এ; আমাদের অবাক করেছিল ধীর job-টা দেখতে কতটা নিরীহ ছিল।
তারপর AI provider বলল: না
নতুন lane merit card-কে বাঁচাল। AI job-কে দ্রুত করল না। lane-টি ধাক্কা খেল provider-এর নিজস্ব rate limit-এ, মিনিটে প্রায় ৭ থেকে ১০টি call, আর একবার provider account-এর credit-ই শেষ হয়ে গিয়েছিল।
দুটিই একই ব্যর্থতা: বাইরের একটি সার্ভিস বলছে "এখন না"। যে retry loop তাকে ক্রমাগত ধাক্কা দেয়, সে শুধু budget পোড়ায় আর failed-jobs table ভরায়, তাই lane-টিকে ধৈর্যশীল করে নতুন করে বানানো হলো। ৬ অক্টোবর থেকে worker-এ Implemented ও চালু:
কৌশল
সেটিং
কী করে
Shared rate limiter
সব worker মিলিয়ে মিনিটে ৮টি
call-কে provider-এর অনুমোদিত সীমার ভেতরে রাখে
Fail নয়, release
Exponential backoff, ১ থেকে ১৫ মিনিট, jitter-সহ
প্রত্যাখ্যাত job queue-তে ফিরে যায়; jitter সবাইকে একসঙ্গে ফিরতে দেয় না
Retry window
সর্বোচ্চ ১২ ঘণ্টা
ভিড় কেটে যাওয়ার অনেক পরেও job চেষ্টা চালিয়ে যায়
Budget refund
মাসিক AI budget counter
প্রত্যাখ্যাত call-এর খরচ ধরা হয় না
Fallback
Template text
এর মধ্যে শিক্ষার্থী একটি সাধারণ narrative দেখে
শিক্ষার্থী কখনো error দেখে না। পেজ খুললেই template text থাকে, আর পালা এলে আসল narrative সেটির জায়গা নেয়।
এক দিনের মধ্যেই এর আসল পরীক্ষা হয়ে গেল। provider account-এর credit শেষ হয়ে গেল, প্রায় ৩,৮০০টি narrative delayed job হিসেবে জমে রইল, কিন্তু একটিও fail করল না। পরদিন দুপুরে credit যোগ হওয়ার কয়েক মিনিটের মধ্যেই প্রথম নতুন narrative লেখা হলো, কোনো restart বা হাতে replay ছাড়াই।
হিসাবে দেখা যায়, window কেন কয়েক ঘণ্টার: মিনিটে ৮টি হারে ২,০০০টি narrative মানে প্রায় চার ঘণ্টার কাজ। কয়েক মিনিটের window হলে বেশিরভাগই বাদ পড়ত।
limiter-টি shared হওয়া জরুরি। দুটি replica আলাদাভাবে মিনিটে ৪টি করে নিজেদের গতি বাঁধলে তা চলে ততক্ষণ, যতক্ষণ কেউ তৃতীয় replica যোগ না করে। একটিই shared counter মোট সংখ্যা ঠিক রাখে, worker যতই থাকুক।
Rate limit: ভবন নয়, শিক্ষার্থীকে গুনুন
rate limiter ততটাই ভালো, যা সে গোনে। আমরা এটি দুই স্তরে দুবার ভুল করেছি, আর দুবারই লক্ষণ ছিল পরীক্ষার মাঝখানে শিক্ষার্থীদের HTTP 429 পাওয়া।
কবে
কী গোনা হচ্ছিল
কী ভুল হলো
সমাধান
২৫ সেপ্টেম্বর
IP ধরে চলা global API limiter (token-ভিত্তিক শিক্ষার্থীদের জন্য default guard ফাঁকা ছিল)
স্কুল বা mobile carrier শত শত শিক্ষার্থীকে একটি NAT IP-র পেছনে রাখে: একটিই ভাগের bucket
শিক্ষার্থী বা instructor account ধরে গোনা, শুধু guest-দের জন্য IP (Implemented)
৭ অক্টোবর
"মিনিটে ৩০" ধরনের route throttle, তখনও client IP ধরে
backend সবার জন্য frontend proxy-র একটিই IP দেখছিল: একটি dashboard endpoint-এর ৭৪% call-এ 429 এসেছে
প্রতি শিক্ষার্থী প্রতি route ধরে গোনা, guest-রা IP ধরে; এরপর এমন 429 ছিল ০টি (Implemented)
প্রতিটি browser API call frontend proxy দিয়ে যায়, তাই per-IP নিয়ম পুরো পরীক্ষার হলকে একজন দর্শনার্থী ভাবে।
দুটি সমাধানের সঙ্গেই test আছে, যেগুলো সমাধান ছাড়া fail করে; দ্বিতীয়টি এক node করে, zero downtime-এ deploy হয়েছে। Planned: frontend থেকে backend-এ শিক্ষার্থীর আসল IP একটি signed header-এ পাঠানো, যাতে প্রতিটি per-IP নিয়ম আর প্রতিটি log লাইন নির্ভুল হয়।
পুরোনো trusted proxy
কাছেই ছোট একটি ঝুঁকি ছিল। backend তখনও পুরোনো frontend server-এর IP বিশ্বাস করত, যে server আমরা মুছে ফেলেছি। cloud কখনো সেই address অন্য কাউকে দিয়ে দিলে সে শিক্ষার্থীর IP জাল করতে পারত। ৭ অক্টোবর আমরা drain-one-node পদ্ধতিতে সেটি সরিয়েছি, এবারও zero downtime-এ। Implemented। trust list আসলে প্রতিশ্রুতির তালিকা; যার মালিক আর নেই, তা মুছে দিন।
যে log node-এর পরেও বেঁচে থাকে
autoscaling-এর যুগে যে মেশিনটি দেখতে চান, সেটি প্রায়ই আর নেই। তাই log লেখার সঙ্গে সঙ্গে node ছেড়ে যেতে হবে। আমাদের container শুধু stdout ও stderr-এ লেখে, আর Fluent Bit backend container-এর log পাঠায় managed OpenSearch-এ, অর্থাৎ ELK-ধাঁচের stack-এ: একটি searchable জায়গা, যা node চলে যাওয়ার পরও থাকে। backend node-এর জন্য Implemented। সাধারণ পদ্ধতিটি আছে Observability for High-Volume Systems-এ।
ক্ষমতা-হিসাবের কাজে এটি নিজের দাম তুলে দিয়েছে। DigitalOcean-এর দুই মিনিটের গড় ৭ অক্টোবরের backend peak দেখিয়েছে ৬৩ request/s; প্রতি মিনিটের log বলেছে প্রায় ৬৯। গড় peak লুকিয়ে ফেলে, আর capacity model-এর দরকার peak।
একটি ফাঁক আছে। frontend node-গুলো এখনও nginx log নিজেদের local disk-এ রাখে, দিনে প্রায় ৪৪০ MB, আর node সরে গেলে সেগুলো হারায়। Planned: frontend node-এও Fluent Bit। ততদিন frontend-ই একমাত্র স্তর, যেখানে scale-in প্রমাণ মুছে দেয়।
আমরা কী দেখি, আর কী করি
আমাদের ops console শুধু পড়তে পারে: নমুনা নেয়, কিছুই বদলায় না। সে রাখে প্রতিটি node ও container-এর CPU, pool-এর CPU, MySQL-এর threads running, connection ও lock wait, Valkey-র memory, client ও operations/s, আর queue-এর স্বাস্থ্য। DigitalOcean-এর নিজস্ব monitoring যোগ করে load balancer-এ request/s আর response class।
পরীক্ষার সময় আমরা এ সবকিছুর দিকে তাকিয়ে থাকি না। প্রতি মিনিটে একটি digest পড়ি: কতজন শিক্ষার্থী শুরু ও জমা দিয়েছে, প্রতি node-এর request ও 5xx, pool CPU, worker load আর failed job। সংখ্যা কম, প্রতিটি একটি সিদ্ধান্তের সঙ্গে বাঁধা।
signal থেকে digest, digest থেকে অল্প কয়েকটি জানা পদক্ষেপের একটি, আর প্রতিটি incident ফিরে আসে runbook-এর নিয়ম হয়ে।
signal দেখে কাজ করা
এই loop-এর হাতে অল্প কয়েকটি পদক্ষেপ আছে, যেগুলো পার্ট ২-এ বর্ণিত:
একটি node drain করা।/lb-health ৫০৩ ফেরত দিলে load balancer প্রায় ৩০ সেকেন্ডের মধ্যে নতুন request পাঠানো বন্ধ করে।
Image rollback করা। আমরা শেষ তিনটি ভালো image রাখি, আর পরীক্ষার সময়ে কখনো template roll করি না।
Pre-scale। বড় পরীক্ষার প্রায় ৪৫ মিনিট আগে pool-এর minimum বাড়ান। reactive scaling কেবল safety net, কারণ DigitalOcean-এর CPU metric আসল load থেকে ৫ থেকে ৮ মিনিট পিছিয়ে থাকে।
৭ অক্টোবর দুই pool-এর পূর্ণ rollout-এর সময় প্রতি ২ সেকেন্ডে একটি uptime probe আসল পেজে আঘাত করেছে: ২১৯টি probe, ০টি error। এভাবেই loop সম্পূর্ণ হয়: বদলাও, দেখো, মাপো।
Scale-in-এর ভুল
৭ অক্টোবরের আসল পরীক্ষার মধ্যে কেউ একজন backend pool-এর minimum কমিয়ে দিলেন। DigitalOcean একটি চালু node-কে drain না করেই সরিয়ে দিল, আর ২ মিনিটে প্রায় ৩৬০টি request ব্যর্থ হলো।
এটা একই সঙ্গে মানুষের হাত ফসকানো আর platform-এর আচরণ: autoscale scale-in drain করে না। নিয়মটি এখন runbook-এ আছে (runbook rule হিসেবে Implemented): পরীক্ষার আগে minimum বাড়ান, আর কমান কেবল পরে। এর সীমাটাও আমরা জানি: runbook-এর নিয়ম কাজ করে মনে রাখার ওপর, আর পরীক্ষার মাঝখানে কেউ ভুলে যেতে পারে। এটা পাহারাদার, তালা নয়।
আমরা যা শিখলাম
stateless node ততটাই নিরাপদ, যতটা নিরাপদ তাদের পেছনের shared store। Valkey-র size ঠিক করুন connection ধরে, শুধু memory ধরে নয়।
প্রতিটি ধরনের কাজের জন্য আলাদা queue। ০.৩৪ সেকেন্ডের job কখনো ১০ সেকেন্ডের job-এর পেছনে অপেক্ষা করবে না।
provider যখন আপনাকে সীমা দেয়, call-এর গতি বাঁধুন, jitter-সহ backoff করুন, কয়েক ঘণ্টা retry করুন, budget refund করুন আর একটি fallback দেখান।
প্রতিটি rate limiter কী গুনছে, তা যাচাই করুন। গণনার একক শিক্ষার্থী; ভবন বা proxy নয়।
log লেখার সঙ্গে সঙ্গে node থেকে সরিয়ে ফেলুন, আর frontend-এর ফাঁকটি incident ঘটার আগেই বন্ধ করুন।
প্রতিটি single point of failure লিখে রাখুন, পাশে অবস্থার label দিয়ে। আমাদেরটি একটি worker, সঙ্গে পরিকল্পিত সমাধান, কোনো ভান নেই।
Autoscale scale-in drain করে না। পরীক্ষার আগে minimum বাড়ান।
পার্ট ৫-এ, সিরিজের শেষ পর্বে, আমরা সবটা জোড়া দিই: ৭ অক্টোবরের আসল পরীক্ষার সন্ধ্যা production-এর সংখ্যা সহ, capacity model, মাসিক খরচ, আর যে load ও soak test এখনও আমাদের নিজেদের কাছে পাওনা।