0 / 0

Interview Prep — A. M. Sadman Rafid

Senior PHP / Laravel · ঢাকা · 2026-08-02
এটা তোমার experience-এর তালিকা না। এটা interviewer যা যাচাই করবে তার তালিকা। ডানপাশের লাইনগুলো মুখে বলার মতো করে লেখা — যেভাবে বললে interviewer বুঝবে, ঠিক সেভাবেই।

✓ marker: যেই প্রশ্নটা তুমি ভালভাবে পারো, তার পাশের গোল বোতামে চাপ দাও — উত্তরটা ভাঁজ হয়ে যাবে, পরেরবার আর সামনে আসবে না। উপরের bar-এ কতটা শেষ হলো দেখা যাবে। Section-এর নামে চাপ দিলে পুরো section ভাঁজ হয়। সব এই browser-এ save থাকে, তাই বন্ধ করে আবার খুললেও যেখানে ছিলে সেখানেই পাবে।

সবুজ লাইন = তোমার নিজের কাজ, উদাহরণ হিসেবে জুড়ে দেবে। ধূসর লাইন = আমার নোট, ওটা বলার জিনিস না।

কীভাবে prepare করবে

পড়ে মুখস্থ করলে কাজ হবে না। এই ছয়টা করলে হবে।

১. JD-কে প্রশ্নে বদলাও
Circular-এর প্রতিটা লাইন ধরে নিজেকে জিজ্ঞেস করো — "এটা যাচাই করতে হলে আমাকে কী প্রশ্ন করবে?" ৮০% প্রশ্ন ওখান থেকেই বেরিয়ে আসে। ওরা কী চায় সেটা তো ওরা নিজেরাই লিখে দিয়েছে।
২. মুখে বলো, পড়ে না
তোমার সমস্যা জানা না, গুছিয়ে বলা। প্রতিটা উত্তর জোরে বলো, ঘড়ি ধরে ২ মিনিটে। ফোনে record করে একবার শুনলেই বুঝবে কোথায় ঘুরপাক খাচ্ছ।
৩. ১০টা গল্প তৈরি রাখো
§১০-এর story bank। একই দশটা গল্প ঘুরিয়ে-ফিরিয়ে চল্লিশ রকম প্রশ্নের উত্তরে কাজে লাগবে।
৪. "কেন" তিনবার
প্রতিটা উত্তরের পর নিজেকে তিনবার জিজ্ঞেস করো কেন। "Redis দিয়েছি" → কেন cache লাগল → কেন Redis, Memcached না → invalidate কীভাবে করলে। Senior interview-এ তৃতীয় "কেন"-তেই বেশিরভাগ লোক আটকায়।
৫. Design কাগজে আঁকো
System design মুখে বলার জিনিস না, আঁকার জিনিস। পাঁচটা system কাগজে এঁকে practice করো — box, arrow, DB, queue, cache। ৪৫ মিনিটে শেষ করার অভ্যাস করো।
৬. CV-র প্রতিটা লাইনে একটা follow-up
CV থেকে যেকোনো লাইন ধরে একটা প্রশ্ন করবেই। যেই লাইনে আটকে যাচ্ছ, হয় সেটা শিখে নাও নয় CV থেকে বাদ দাও। এই একটা কাজ সবচেয়ে দ্রুত ফল দেয়।

সময় কম থাকলে এই ক্রমে পড়ো: §৫ System design → §২ Laravel internals → §৩ Database → §৯ Behavioural। বাকিগুলো তুমি এমনিতেই জানো, শুধু ঝালাই দিলেই হবে।

PHP internals

Zend certification আছে বলে এখানে একটু বেশি গভীরে জিজ্ঞেস করবে। প্রস্তুত থেকো।

abstract class, interface আর trait-এর পার্থক্য?
Interface হলো একটা চুক্তি — class-এ কোন কোন method থাকতেই হবে সেটা বলে দেয়, কিন্তু কীভাবে কাজ করবে বলে না। Abstract class-ও চুক্তি করে, তবে সাথে কিছু তৈরি code-ও দিয়ে দিতে পারে যেটা সব child পাবে। আর trait হলো কয়েকটা class-এ একই code বারবার না লিখে একবার লিখে সবার মধ্যে ব্যবহার করা। Interface যতগুলো ইচ্ছা নেওয়া যায়, কিন্তু extend করা যায় একটাই class।
কখন কোনটা নেবে?
কাজটা এক কিন্তু করার উপায় আলাদা হলে আমি interface নিই — যেমন payment, bKash আর Stripe দুটোই টাকা কাটে কিন্তু ভিতরে সম্পূর্ণ আলাদা। যদি সবার জন্য কিছু common code লাগে, তখন abstract class। আর একদম সম্পর্কহীন class-গুলোতে একই ছোট কাজ লাগলে trait।
$this, self আর static?
$this মানে এই object-টা। self মানে যেই class-এর ভিতরে লাইনটা লেখা আছে, সেই class। আর static মানে যেই class থেকে ডাকা হয়েছে সেটা — child থেকে ডাকলে child-কেই বোঝাবে।
Late static binding কেন দরকার?
Parent class-এ যদি new self() লিখি, তাহলে child থেকে ডাকলেও parent-এর object-ই বানাবে, যেটা আমি চাইনি। new static() লিখলে যেই class থেকে ডেকেছি তারটাই বানায়। Laravel-এ Model::query() এইভাবেই সঠিক model ফেরত দিতে পারে।
Magic method কী, কোথায় কাজে লাগে?
এগুলো PHP-র কিছু বিশেষ method যেগুলো আমি না ডাকলেও নিজে থেকে চলে। যেমন কোনো property না থাকলে __get চলে, method না থাকলে __call। Laravel-এর Facade আসলে __callStatic দিয়ে বানানো, আর Eloquent-এ $user->name কাজ করে __get দিয়ে।
PHP 8-এ কী কী নতুন এসেছে?
আমি সবচেয়ে বেশি ব্যবহার করি enum, readonly property, constructor-এর ভিতরেই property লিখে ফেলা, match, named argument আর attribute। এর মধ্যে attribute দিয়ে আমি নিজের framework-এ routing বানিয়েছি — controller-এর method-এর উপরেই route লিখে দেওয়া যায়।
match আর switch-এর পার্থক্য?
match কঠোরভাবে মেলায়, মানে === দিয়ে — তাই "1" আর 1 এক না। এটা সরাসরি একটা মান ফেরত দেয়, break লিখতে হয় না, আর কোনো case না মিললে চুপ করে না থেকে error দেয়। এই শেষ জিনিসটার জন্যই আমি match পছন্দ করি — ভুল চুপচাপ পার পায় না।
enum কেন ব্যবহার করবে?
আগে status-এর জন্য 'pending', 'paid' এইভাবে string লিখতাম। বানান ভুল হলে ধরা পড়ত অনেক পরে, DB-তে গিয়ে। Enum দিয়ে মানগুলো নির্দিষ্ট করা থাকে, ভুল লিখলে সাথে সাথে error দেয় আর editor-ও suggest করে।
opcache কী করে?
PHP প্রতিবার file পড়ে, compile করে, তারপর চালায়। Opcache ওই compile করা জিনিসটা memory-তে রেখে দেয়, তাই পরের request-এ আর compile করতে হয় না। Production-এ এটা বন্ধ থাকলে অনেকটা গতি এমনিতেই নষ্ট হয়।
Generator বা yield কেন লাগে?
অনেক বড় data ঘোরাতে গেলে পুরোটা array-তে তুললে memory শেষ হয়ে যায়। yield দিয়ে একটা একটা করে দেওয়া যায় — দশ লাখ লাইনের file পড়লেও memory একই থাকে, কারণ একসাথে একটা লাইনই ধরা থাকে।
PHP memory কীভাবে ছাড়ে?
PHP গুনে রাখে একটা জিনিসকে কতজন ধরে আছে। সেই সংখ্যা শূন্য হলেই memory ছেড়ে দেয়। আর দুইটা object যদি একে অপরকে ধরে থাকে, তখন সংখ্যা কখনো শূন্য হয় না — ওটা আলাদা একটা garbage collector পরিষ্কার করে।
Array কি reference-এ যায়?
না, value-তে যায়। তবে PHP সাথে সাথে copy করে না — যতক্ষণ কেউ বদলাচ্ছে না ততক্ষণ একই জিনিসই ব্যবহার হয়, কেউ বদলালে তখন copy হয়। তাই বড় array function-এ পাঠাতে ভয় নেই।
== আর ===?
== type বদলে তুলনা করে, তাই "0" আর false এক হয়ে যায়। === type সহ মেলায়। আমি সবসময় === ব্যবহার করি, কারণ এই ধরনের bug খুঁজে বের করা সবচেয়ে কঠিন — কোথাও error দেয় না, শুধু ভুল ফল দেয়।
Closure-এ বাইরের variable আনবে কীভাবে?
use দিয়ে। সাধারণভাবে একটা copy যায়, আর & দিলে আসলটাই যায়। এছাড়া Closure::bind দিয়ে closure-এর ভিতরে $this কে বদলে দেওয়া যায় — Laravel অনেক জায়গায় এটা করে।
Dependency Injection কী, লাভ কী?
Class নিজে তার dependency বানাবে না, বাইরে থেকে দেওয়া হবে। এতে দুইটা লাভ — constructor দেখলেই বোঝা যায় class-টা কীসের উপর নির্ভর করে, আর test করার সময় আসল জিনিসের বদলে নকল একটা বসিয়ে দেওয়া যায়।
PSR কী?
PHP-র কিছু সাধারণ নিয়ম, যাতে আলাদা আলাদা লোকের লেখা code একসাথে চলতে পারে। আমি প্রতিদিন যেগুলো ব্যবহার করি — PSR-4 autoloading আর PSR-12 code style। এছাড়া PSR-7 HTTP message আর PSR-11 container-ও কাজে লাগে।

Laravel internals

"Laravel ব্যবহার করতে পারি" আর "Laravel কীভাবে কাজ করে জানি" — এই section-টাই দুইটার পার্থক্য।

একটা request শুরু থেকে শেষ পর্যন্ত কী কী পার হয়?
Request প্রথমে public/index.php-তে আসে। ওখানে autoload হয়, তারপর application তৈরি হয়ে HTTP Kernel-এ যায়। Kernel প্রথমে env আর config load করে, exception handler বসায়, তারপর সব service provider আগে register করে পরে boot করে। এরপর request middleware-গুলোর ভিতর দিয়ে যায়, route মেলে, controller চলে। Controller যেই response দেয় সেটা আবার middleware-এর উল্টো পথে ফিরে user-এর কাছে যায়, আর সবার শেষে terminate middleware চলে — যেমন session লেখা। এই একটা উত্তর ভাল দিলে interviewer ধরে নেয় তুমি Laravel সত্যিই চেনো। এইটা মুখস্থ করে ফেলো।
Service container কী?
এটা এমন একটা জায়গা যেখানে লেখা থাকে কোন class কীভাবে বানাতে হবে। Constructor-এ শুধু type লিখে দিলে container নিজেই দেখে নেয় কী কী লাগবে, বানিয়ে ঢুকিয়ে দেয়। তাই আমাকে হাতে new লিখে dependency জোগাড় করতে হয় না।
bind আর singleton?
bind করলে যতবার চাইব ততবার নতুন object পাব। singleton করলে প্রথমবার একটা বানিয়ে রেখে দেয়, এরপর সবাই ওই একটাই পায়। যেগুলো বানাতে খরচ বেশি বা যেগুলোর ভিতরে কিছু জমিয়ে রাখতে হয়, সেগুলো singleton করি।
register() আর boot()-এর পার্থক্য?
register()-এ আমি শুধু container-এ জিনিস bind করি, অন্য কোনো service ছুঁই না — কারণ তখনও সব provider register হয়নি, ওটা তখন নাও থাকতে পারে। boot() চলে সব register হয়ে যাওয়ার পর, তাই ওখানে অন্য service ব্যবহার করা নিরাপদ। Event listener, view composer, route — এগুলো boot-এ যায়।
Facade আসলে কী? ওটা কি static?
দেখতে static মনে হলেও আসলে না। Cache::get() লিখলে PHP __callStatic ধরে, সেটা container থেকে আসল cache object-টা বের করে আনে, তারপর তার উপর get() চালায়। কোন object আনবে সেটা getFacadeAccessor() বলে দেয়।
Facade না DI — তুমি কোনটা নাও?
আমি সাধারণত DI নিই, কারণ constructor দেখলেই বোঝা যায় class-টা কীসের উপর নির্ভর করে, আর test-এ নকল বসানো সহজ। Facade লিখতে দ্রুত, কিন্তু নির্ভরতাগুলো লুকিয়ে ফেলে — class-টা কত জিনিস ব্যবহার করছে বাইরে থেকে বোঝা যায় না।
Middleware কীভাবে কাজ করে?
Middleware গুলো একটার ভিতরে আরেকটা সাজানো থাকে, অনেকটা পেঁয়াজের খোসার মত। প্রতিটা middleware তার কাজ করে $next($request) ডাকে, তাই request ভিতরের দিকে যেতে থাকে। Controller-এর response আবার উল্টো পথে সবার ভিতর দিয়ে ফিরে আসে। এই কারণেই একই middleware-এ request-এর আগেও কাজ করা যায়, response তৈরি হওয়ার পরেও।
Global আর route middleware?
Global middleware প্রতিটা request-এ চলে, route middleware শুধু নির্দিষ্ট route-এ — যেমন auth বা throttle। ভারী কোনো কাজ আমি কখনো global-এ দিই না, কারণ তাহলে যেই request-এর দরকার নেই সেটাও ধীর হয়ে যায়।
Deferred service provider?
যেই service সব request-এ লাগে না, সেটাকে deferred করে রাখলে দরকার না পড়া পর্যন্ত load হয় না। এতে app boot হালকা থাকে।
Eloquent-এ কী কী relation আছে?
hasOne আর hasMany — এক জিনিসের নিচে এক বা একাধিক। belongsTo তার উল্টো দিক। belongsToMany যখন দুই দিকেই অনেক, মাঝে একটা pivot table থাকে। আর polymorphic — যেমন comment, সেটা post-এও থাকতে পারে video-তেও, তখন এক টেবিলেই দুই জায়গার comment রাখা যায়।
N+1 problem কী, কীভাবে ধরো?
একশোটা post এনে loop-এ প্রতিটার লেখকের নাম চাইলে একশো একটা query হয়ে যায় — একটা post আনতে, আর একশোটা লেখক আনতে। with('author') দিলে দুইটা query-তেই শেষ। ধরার জন্য Telescope বা Debugbar দিয়ে query count দেখি। তুমি নিজেই eloquent-pulse নামে একটা VS Code extension বানিয়েছ যেটা কোড লেখার সময়ই query-গুলো দেখায় — এই প্রশ্নের উত্তরে ওটা বলবে, খুব ভাল লাগবে।
with() আর load()?
with() query চালানোর আগে বলে দেয় কী কী একসাথে আনতে হবে। load() ব্যবহার করি যখন data ইতিমধ্যে হাতে চলে এসেছে, তারপর মনে হলো relation-টাও লাগবে।
দশ লাখ row process করবে কীভাবে?
all() কখনো করি না, সব memory-তে উঠে যাবে। chunkById() দিয়ে হাজার হাজার করে ভাগ করে নিই, অথবা cursor() বা lazy() দিয়ে একটা একটা করে। chunkById বেশি নিরাপদ কারণ মাঝখানে data বদলালেও row বাদ পড়ে না।
Observer আর Event?
Observer model-এর সাথে বাঁধা — created, updated, deleted এসব ধরে। Event model-এর সাথে বাঁধা না, ওটা business-এর একটা ঘটনা, যেমন OrderPlaced। আমি model-এর ছোট কাজগুলো observer-এ রাখি, আর যেই ঘটনার সাথে অনেক কিছু জড়িত সেটা event-এ — কারণ পরে নতুন কাজ যোগ করতে শুধু একটা listener বাড়ালেই হয়, পুরনো code ছুঁতে হয় না।
Job fail করলে কী হয়?
কতবার চেষ্টা করবে সেটা tries দিয়ে ঠিক করি, আর দুই চেষ্টার মাঝে কত সময় থামবে সেটা backoff। সব চেষ্টা শেষ হলে job টা failed_jobs table-এ চলে যায়, পরে দেখা বা আবার চালানো যায়। আর failed() method-এ আমি alert পাঠাই বা যা আধা-কাজ হয়েছিল সেটা পরিষ্কার করি।
Job কেন idempotent রাখতে হয়?
Queue একই job একাধিকবার চালাতে পারে — worker হঠাৎ বন্ধ হলে বা retry হলে। তাই job এমনভাবে লিখতে হয় যে দুইবার চললেও দুইবার টাকা কাটবে না বা দুইবার mail যাবে না। সাধারণত একটা unique key রাখি বা কাজ শুরুর আগে status দেখে নিই।
Queue driver কোনটা কখন?
ছোট project-এ database driver-ই যথেষ্ট, আলাদা কিছু লাগে না। চাপ বাড়লে Redis নিই, আর তখন Horizon দিয়ে দেখা যায় কোন queue-তে কত জমেছে আর কোনটা fail করছে। AWS-এ থাকলে SQS। অনেকগুলো job একসাথে চালিয়ে সবার শেষে কিছু করতে হলে Bus::batch
config:cache-এর পর env() কাজ করে না কেন?
Cache করার পর Laravel আর .env file পড়ে না, একটা তৈরি করা file থেকে config নেয়। তাই controller বা service-এ env() লিখলে সেটা null আসবে আর production-এ হঠাৎ জিনিস ভেঙে যাবে। এই কারণে আমি env() শুধু config folder-এর ভিতরে ব্যবহার করি, আর কোথাও না।
Collection আর Query Builder?
Query Builder-এ যা লিখি সেটা DB-তে গিয়ে হয়, Collection-এ যা লিখি সেটা PHP-র memory-তে। তাই এক লাখ row এনে collection-এ filter করা মানে DB-র কাজটা PHP দিয়ে করা — ওই where টা query-তেই দেওয়া উচিত ছিল। এই ভুলটা নতুনদের code-এ আমি প্রায়ই দেখি।
Local আর global scope?
Local scope হলো বারবার লাগা কোনো শর্তের একটা নাম দিয়ে রাখা, যেমন scopeActive। Global scope নিজে থেকেই প্রতিটা query-তে জুড়ে যায় — soft delete আর multi-tenant এইভাবেই কাজ করে। এর সুবিধা হলো কেউ লিখতে ভুলে গেলেও data মিশে যায় না।
Repository pattern কি সবসময় লাগে?
না। Eloquent নিজেই DB-র উপর একটা layer, তার উপর আরেকটা layer দিলে অনেক সময় শুধু file-ই বাড়ে। আমি তখনই নিই যখন একই query অনেক জায়গায় লাগছে, বা data একাধিক জায়গা থেকে আসছে। শুধু "pattern ভাল" বলে নিই না। এইভাবে উত্তর দিলে বোঝা যায় তুমি pattern মুখস্থ করোনি, বুঝে ব্যবহার করো — এইটাই ওরা দেখতে চায়।
Validation কোথায় লেখো?
FormRequest-এ। Controller-এ লিখলে controller বড় হয়ে যায়, আর একই নিয়ম অন্য কোথাও লাগলে আবার লিখতে হয়। FormRequest-এ থাকলে authorization-ও ওখানেই বসানো যায়।
API Resource কেন দরকার?
Model সরাসরি ফেরত দিলে DB-তে নতুন column যোগ করলেই API-র response বদলে যায়, আর কখনো গোপন কিছুও বেরিয়ে যেতে পারে। Resource দিয়ে আমি ঠিক করে দিই বাইরে কী কী যাবে, ফলে DB আর API আলাদা থাকে — একটা বদলালে অন্যটা ভাঙে না।

Database

Senior interview-এ index আর transaction — এই দুইটা প্রায় নিশ্চিত আসবে।

Index কীভাবে কাজ করে?
Index হলো আলাদা করে সাজিয়ে রাখা একটা তালিকা, অনেকটা বইয়ের শেষের index-এর মত। সাজানো থাকে বলে পুরো table না পড়েই row খুঁজে পাওয়া যায়। বিনিময়ে প্রতিবার লেখার সময় ওই তালিকাটাও update করতে হয়, তাই ইচ্ছামত index দেওয়া যায় না।
Composite index-এ column-এর ক্রম কেন গুরুত্বপূর্ণ?
a, b, c দিয়ে একটা index বানালে সেটা কাজ করে যদি where-এ a থাকে, বা a আর b, বা তিনটাই। কিন্তু শুধু b দিয়ে খুঁজলে index কাজে লাগে না, কারণ সাজানোটা হয়েছে আগে a ধরে — ঠিক ফোনবুকের মত, নাম জানলে খুঁজে পাবে, শুধু পদবি জানলে না। এই প্রশ্নটা প্রায় সব senior interview-এ আসে। ফোনবুকের উদাহরণটা দিলে interviewer সাথে সাথে বোঝে তুমি জিনিসটা বুঝে বলছ।
EXPLAIN-এ কী দেখো?
প্রথমে দেখি type — ওখানে ALL লেখা থাকলে বুঝি পুরো table পড়ছে, ওটাই সমস্যা। তারপর key দেখি কোন index লেগেছে, আর rows দেখি কত row ছুঁচ্ছে। শেষে Extra-তে Using filesort বা Using temporary দেখলে বুঝি order by বা group by index কাজে লাগাতে পারছে না।
একটা query slow — কী করো?
প্রথমে EXPLAIN চালাই, তারপর দেখি where আর order by-র column-এ index আছে কিনা। SELECT * থাকলে দরকারি column-এ নামিয়ে আনি। একটা ভুল আমি প্রায়ই দেখি — where-এ column-এর উপর function লাগানো, যেমন DATE(created_at) = ...; ওতে index কাজ করে না, তাই ওটা দুইটা তারিখের মাঝের range-এ ভেঙে দিই। এতেও না হলে তখন cache বা আগে থেকে হিসাব করে রাখার কথা ভাবি। তোমার ২০ সেকেন্ড থেকে ৩০০ মিলিসেকেন্ডে নামানোর গল্পটা ঠিক এইখানে বলবে।
Index কখন দেবে না?
যেই column-এ মান প্রায় একই রকম, যেমন is_active — সেখানে index দিয়ে লাভ নেই, কারণ অর্ধেক table এমনিতেই মিলে যায়। আর যেই table-এ পড়ার তুলনায় লেখা অনেক বেশি, সেখানে বেশি index দিলে লেখাটাই ধীর হয়ে যায়।
Transaction isolation level?
চারটা আছে। READ UNCOMMITTED-এ অন্যের অসমাপ্ত কাজও দেখা যায়, ওটা কেউ ব্যবহার করে না। READ COMMITTED-এ শুধু commit হয়ে যাওয়া data দেখা যায়। MySQL-এর default হলো REPEATABLE READ — একই transaction-এর ভিতরে বারবার পড়লে একই ফল পাব, মাঝখানে অন্য কেউ বদলালেও। আর SERIALIZABLE সবচেয়ে নিরাপদ কিন্তু সবচেয়ে ধীর, কারণ ওখানে একজনের পর একজন চলে।
Deadlock কেন হয়, কী করো?
দুইটা transaction যদি উল্টো ক্রমে দুইটা row lock করে, তাহলে দুইজনই অন্যজনের জন্য বসে থাকে আর কেউই এগোতে পারে না। আমি তিনভাবে সামলাই — সবাই যেন একই ক্রমে lock করে সেটা নিশ্চিত করি, transaction যত ছোট রাখা যায় রাখি, আর deadlock হলে ওই কাজটা আবার চেষ্টা করার ব্যবস্থা রাখি।
Pessimistic আর optimistic lock?
Pessimistic হলো আগেই ধরে রাখা — SELECT ... FOR UPDATE দিয়ে row টা lock করে ফেলি, অন্য কেউ ছুঁতে পারে না। Optimistic হলো ধরে না রেখে একটা version column রাখা; লেখার সময় মিলিয়ে দেখি মাঝখানে কেউ বদলেছে কিনা, বদলে থাকলে আবার চেষ্টা করি। টাকা বা সিটের মত জায়গায় pessimistic নিই, আর যেখানে সংঘর্ষ কম সেখানে optimistic।
দশ লাখ row-এর table-এ পিছনের page slow কেন?
LIMIT 100000, 20 লিখলে DB আসলে এক লাখ বিশটা row পড়ে, তারপর প্রথম এক লাখ ফেলে দেয় — তাই যত পিছনের page তত ধীর। বড় list-এ আমি cursor pagination ব্যবহার করি, মানে শেষ id মনে রেখে where id > ওই id দিয়ে পরের বিশটা আনা। তখন প্রথম page আর হাজারতম page একই গতিতে আসে।
Soft delete-এর সমস্যা কী?
দুইটা। এক, প্রতিটা query-তে deleted_at is null যোগ হয়, তাই index-এও deleted_at রাখতে হয়, নাহলে ধীর হয়ে যায়। দুই, unique constraint ভেঙে যায় — মুছে ফেলা email এখনো table-এ পড়ে আছে, তাই একই email দিয়ে আর account খোলা যায় না। এটা সামলাতে হয় unique-এ deleted_at যোগ করে।
Normalize না denormalize?
আমি normalized দিয়েই শুরু করি, তাতে data এক জায়গায় থাকে আর ভুল কম হয়। পরে যদি দেখি কোনো পাতা বারবার একই join করছে আর ধীর হচ্ছে, তখন ওই নির্দিষ্ট জায়গায় denormalize করি — যেমন গোনার সংখ্যাটা আলাদা column-এ রেখে দেওয়া। আগে থেকেই করি না, কারণ তখন সমস্যাটা আদৌ আছে কিনা সেটাই জানি না।
বড় table-এ column যোগ করবে কীভাবে?
MySQL 8-এ অনেক ALTER এখন online হয়, table lock হয় না। তবু আমি আগে staging-এ চালিয়ে দেখি কত সময় লাগে, আর কখনো peak time-এ দিই না। খুব বড় হলে নতুন table বানিয়ে ধীরে ধীরে data সরানোর পথে যাই।

API + Auth

ভাল REST API design কেমন?
URL-এ কাজের নাম না দিয়ে জিনিসের নাম দিই — /orders, /orders/5। কী করছি সেটা HTTP method বলে দেয়, তাই /getOrders লেখার দরকার নেই। আর status code ঠিকভাবে দিই, কারণ frontend ওটার উপর ভিত্তি করেই সিদ্ধান্ত নেয়।
401 আর 403?
401 মানে তুমি কে সেটাই জানি না — login করোনি বা token নেই। 403 মানে জানি তুমি কে, কিন্তু এই কাজটা করার অনুমতি তোমার নেই।
Sanctum, Passport না JWT?
নিজের app-এর জন্য, মানে আমার নিজের SPA বা mobile app, আমি Sanctum নিই — হালকা, token DB-তে থাকে, তাই কাউকে বের করে দেওয়া সহজ। অন্য কোম্পানিকে আমার API ব্যবহার করতে দিতে হলে Passport, কারণ তখন পুরো OAuth2 লাগে। আর অনেকগুলো আলাদা service থাকলে JWT ভাল, কারণ প্রতিটা service নিজেই token যাচাই করতে পারে, প্রতিবার auth service-এ যেতে হয় না।
JWT বাতিল করা কঠিন কেন?
JWT-তে সব তথ্য token-এর ভিতরেই থাকে, server কিছু মনে রাখে না — এটাই এর সুবিধা, আবার এটাই সমস্যা। কাউকে বের করে দিতে চাইলে token তো তার হাতেই আছে, server-এর কিছু মোছার নেই। তাই আমি expiry ছোট রাখি, পনেরো মিনিটের মত, সাথে একটা refresh token দিই। আর সত্যিই জরুরি হলে একটা blacklist রাখতে হয়, তবে তখন stateless থাকার সুবিধাটা কিছুটা চলে যায়।
Idempotency কী, কেন লাগে?
User দুইবার button চাপল, বা network fail করে request আবার গেল — তখন যেন দুইবার order না হয়, সেটা নিশ্চিত করা। Client প্রতিটা request-এর সাথে একটা unique key পাঠায়, server ওই key ধরে ফলটা রেখে দেয়। একই key আবার এলে নতুন কিছু না করে আগের ফলটাই ফেরত দেয়। Payment-এ এটা না থাকলে দুইবার টাকা কাটার ঘটনা ঘটবেই। তুমি bKash, Nagad, SSLCommerz আর Stripe — চারটাই করেছ। এই উত্তরের শেষে ওটা বলবে।
Webhook নিরাপদে handle করবে কীভাবে?
চারটা জিনিস দেখি। Signature মিলিয়ে নিশ্চিত হই সত্যিই gateway পাঠিয়েছে, নাহলে যে কেউ ভুয়া payment success পাঠাতে পারবে। একই event দুইবার আসবে ধরে নিয়ে idempotent রাখি। সাথে সাথে 200 দিয়ে দিই আর আসল কাজটা queue-তে ফেলি, নাহলে timeout হলে ওরা বারবার পাঠাতে থাকবে। আর ব্যর্থ হলে ওরা retry করবে, সেটা মাথায় রেখেই লিখি।
API versioning কীভাবে করো?
আমি URL-এ রাখি, /api/v1। দেখলেই বোঝা যায়, cache করা সহজ, আর পুরনো mobile app গুলো v1-এ চলতে থাকে যখন নতুনটা v2-তে চলে যায়। Header দিয়েও করা যায়, দেখতে সুন্দর, কিন্তু debug করা কষ্ট।
Rate limit?
throttle middleware দিয়ে, গোনাটা Redis-এ হয়। User login করা থাকলে user ধরে গুনি, না থাকলে IP ধরে। আর যেই endpoint ভারী — যেমন search বা report — সেখানে আলাদা করে কম সীমা দিই।
Error response কেমন হওয়া উচিত?
সব error একই আকারে পাঠাই — একটা message, আর validation হলে field ধরে errors। তাহলে frontend একবার handle লিখলেই সব জায়গায় কাজ করে, প্রতিটা API-র জন্য আলাদা করে ভাবতে হয় না।
API document করো কীভাবে?
Swagger দিয়ে, l5-swagger package ব্যবহার করে — code-এর সাথেই থাকে বলে সহজে পুরনো হয়ে যায় না। সাথে একটা Postman collection দিয়ে রাখি, যেন frontend-এর লোক সরাসরি চালিয়ে দেখতে পারে।

System design ★ সবচেয়ে ভারী

এইটাই senior-এর আসল পরীক্ষা। ওরা কোড দেখবে না, তুমি কীভাবে ভাবো সেটা দেখবে।

৭ ধাপের নিয়ম — যেকোনো design প্রশ্নে এই ক্রমেই যাবে

  1. আগে প্রশ্ন করো। কত user, দিনে কত request, পড়া বেশি না লেখা বেশি, কোনটা must আর কোনটা পরে হলেও চলবে। সাথে সাথে design শুরু করাটাই সবচেয়ে বড় ভুল।
  2. API লিখে ফেলো। কোন endpoint, কী নেবে, কী দেবে।
  3. Data model আঁকো। কী কী table, কার সাথে কার সম্পর্ক, কোথায় index।
  4. বড় ছবিটা আঁকো। Client → load balancer → app → cache → DB, পাশে queue আর worker।
  5. কোথায় আগে ভাঙবে বলো। তারপর সেই জায়গায় cache, queue, index বা read replica।
  6. ভাঙার কথা বলো। DB পড়ে গেলে কী হবে, queue জমে গেলে, একই request দুইবার এলে।
  7. Trade-off বলো। "এই পথটা নিলাম কারণ এটা, বিনিময়ে এই জিনিসটা হারালাম।" এই শেষ ধাপটাই senior আর mid-এর পার্থক্য।

যেই ৫টা প্রশ্ন সবচেয়ে বেশি আসে — প্রতিটার উত্তর মুখে বলার মতো করে।

১. একটা booking system design করো — একই সিট দুইজন যেন না পায়
আসল সমস্যাটা হলো একই মুহূর্তে দুইজন একই সিট চাইলে কী হবে। শুধু কোডে "সিট খালি আছে কিনা" দেখলে হবে না, কারণ দুইজনই একসাথে দেখবে আর দুইজনই খালি পাবে। তাই আমি DB-র উপর ভরসা করি — booking table-এ সিট আর show মিলিয়ে unique constraint দিই, আর transaction-এর ভিতরে row lock করে নিই যেন একজন ঢুকলে অন্যজনকে অপেক্ষা করতে হয়। সাথে একটা সময়সীমা রাখি, ধরে রেখে নির্দিষ্ট সময়ে টাকা না দিলে সিট আবার খালি হয়ে যায়।
২. একটা notification service design করো
প্রথমেই সব notification queue-তে দিই, সরাসরি পাঠাই না — নাহলে user-এর request ওই SMS gateway-র জন্য আটকে থাকবে। প্রতিটা channel-এর আলাদা worker রাখি, কারণ email ধীর হলে push যেন আটকে না যায়। Fail করলে কয়েকবার চেষ্টা করে, আর একটা key দিয়ে দেখি একই জিনিস আগে পাঠিয়েছি কিনা যেন duplicate না যায়। Template গুলো আলাদা রাখি যাতে লেখা বদলাতে code deploy করতে না হয়। আর একটা vendor বসে গেলে আরেকটায় যাওয়ার ব্যবস্থা রাখি।
৩. Multi-tenant SaaS কীভাবে করবে?
তিনভাবে করা যায় — সবাই এক DB-তে tenant_id দিয়ে আলাদা, বা প্রতি tenant-এর আলাদা schema, বা একদম আলাদা DB। আমি সাধারণত প্রথমটা নিই, কারণ খরচ কম আর migration একবারই চালাতে হয়। তবে এর সবচেয়ে বড় ঝুঁকি হলো কোথাও tenant_id দিতে ভুলে যাওয়া — তাই আমি global scope দিয়ে ওটা বাধ্যতামূলক করে দিই, হাতে লিখতে হয় না। আর cache key-তেও tenant id ঢোকাতে হয়, নাহলে এক tenant আরেকজনের cache করা data দেখে ফেলবে। এইটা তুমি সত্যিই বানিয়েছ, per-tenant cache invalidation সহ। শেষ লাইনটা বলার পর "এই জিনিসটা আমি নিজে ভুগে শিখেছি" যোগ করলে উত্তরটা আরও বিশ্বাসযোগ্য হয়।
৪. বড় file বা video upload আর processing?
বড় file server দিয়ে পাঠাই না। Backend থেকে একটা presigned URL দিই, browser সরাসরি S3-তে upload করে — এতে server-এর উপর কোনো চাপ পড়ে না। Upload শেষ হলে একটা record বানাই status pending দিয়ে, আর processing-টা queue-তে চলে যায়। কাজ শেষ হলে status বদলাই আর user-কে জানাই।
৫. একটা dashboard খুব slow — কী করবে?
প্রথমে মেপে দেখি ঠিক কোনটা ধীর, সাধারণত দুই-তিনটা বড় aggregate query-ই পুরো পাতা আটকে রাখে। ওগুলোর ফল cache-এ রাখি, বা রাতে হিসাব করে আলাদা একটা table-এ রেখে দিই যাতে পাতাটা শুধু পড়ে নেয়। ভারী report গুলো queue-তে সরিয়ে দিই, তৈরি হলে download link দিই। এতেও না হলে পড়ার জন্য read replica।
Cache invalidate করবে কীভাবে?
তিনটা উপায়। TTL দিয়ে সময় শেষে নিজে থেকে মুছে যাওয়া — সহজ, কিন্তু ততক্ষণ পুরনো data দেখাবে। Data বদলালেই cache মুছে দেওয়া — সঠিক, কিন্তু কোথাও মুছতে ভুলে গেলে সমস্যা। আর tag দিয়ে একসাথে অনেকগুলো মোছা। আমি সাধারণত দুইটাই মেশাই — মুছেও দিই, আবার একটা TTL-ও রাখি নিরাপত্তার জন্য।
Cache stampede কী?
খুব জনপ্রিয় একটা cache expire হওয়ার মুহূর্তে হাজারটা request একসাথে দেখে cache নেই, আর সবাই একসাথে DB-তে গিয়ে পড়ে — DB তখনই বসে যায়। সমাধান হলো lock দেওয়া, একজন গিয়ে বানাবে আর বাকিরা অপেক্ষা করবে। আর TTL-এ একটু random সময় যোগ করি, যেন সব cache একসাথে না মরে।
Read replica ব্যবহারের সমস্যা?
Master-এ লেখার পর replica-তে পৌঁছাতে একটু সময় লাগে। তাই user কিছু save করে সাথে সাথে পাতা refresh করলে পুরনো data দেখতে পারে, আর সে ভাববে save হয়নি। এই কারণে লেখার পরপর ওই user-এর পড়াটা master থেকে নিই, বাকি সবার replica থেকে।
Queue জমে গেলে?
প্রথমে দেখি কোন job জমছে। ভারী job গুলো আলাদা queue-তে সরাই যেন ছোট কাজগুলো ওগুলোর পিছনে আটকে না থাকে, আর worker বাড়াই। জরুরি জিনিসের জন্য আলাদা priority queue রাখি। তবে সবচেয়ে জরুরি হলো queue depth-এ alert বসানো — নাহলে জমছে সেটা জানতেই পারব না যতক্ষণ না user অভিযোগ করে।

Security

এইগুলো এক লাইনে বলতে পারলেই যথেষ্ট। Laravel কীভাবে সামলায় সেটা বলাই আসল উত্তর।

ঝুঁকিতুমি যা বলবে
SQL InjectionEloquent আর Query Builder নিজেই binding ব্যবহার করে, তাই এমনিতে নিরাপদ। ঝুঁকি তৈরি হয় DB::raw-তে হাতে string জোড়া দিলে — ওখানে আমি সবসময় binding দিই।
XSSBlade-এর {{ }} নিজেই escape করে দেয়। {!! !!} শুধু তখনই ব্যবহার করি যখন HTML-টা আমার নিজের, user-এর দেওয়া কিছুতে কখনো না।
CSRFForm-এ @csrf token, আর middleware সেটা মিলিয়ে দেখে। API-তে token ভিত্তিক auth থাকলে এটা লাগে না।
Mass assignment$fillable দিয়ে বলে দিই কোন field গুলো বাইরে থেকে আসতে পারে। ওটা খোলা রেখে $request->all() দিলে কেউ is_admin পাঠিয়ে দিতে পারে।
Access control (IDOR)Login করা মানেই সব দেখার অধিকার না। /orders/5 এলে দেখি ওটা আসলেই এই user-এর কিনা — Policy দিয়ে করি, তাহলে সব জায়গায় একই নিয়ম থাকে।
File uploadmime আর size যাচাই করি, file-এর নাম নিজে বানাই, আর public folder-এর বাইরে রাখি। দেখাতে হলে signed URL দিই।
Sensitive dataPassword bcrypt বা argon2-তে, .env কখনো repo-তে না, আর log-এ token বা card number যাতে না যায় সেটা দেখি।
SSRFUser-এর দেওয়া URL-এ server থেকে সরাসরি request মারি না, whitelist করে নিই।
Dependencycomposer audit চালাই। পুরনো package-ই সবচেয়ে সহজ ফাঁক, আর ওটা নিজের code দেখে ধরা যায় না।
"তুমি নিজে security নিয়ে কী করো?"
Validation আলাদা layer-এ রাখি, authorization policy দিয়ে করি, secret কখনো repo-তে যায় না, আর dependency-র advisory দেখি। শেষেরটা নিয়ে একটা বাস্তব ঘটনা আছে — আমার নিজের framework-এ CI হঠাৎ লাল হয়ে গেল, অথচ আমার Docker-এ সব ঠিকঠাক চলছিল। দেখলাম যেই JWT package ব্যবহার করছিলাম তার পুরো একটা version series-এর উপর security advisory আছে, আর নতুন Composer ওটা install করতেই রাজি না। আমার Docker image-এর Composer পুরনো ছিল বলে সে advisory-টা চিনতই না। Package-এর পরের major version-এ গিয়ে সমাধান করেছি, আর harness-টা ঠিক করেছি যেন সে নিজে থেকে Composer update করে নেয় — তাহলে local আর CI একই নিয়ম মানে। এইটাই "security নিয়ে কী করো" প্রশ্নের সবচেয়ে ভাল উত্তর, কারণ এটা তোমার সাথে সত্যিই ঘটেছে আর repo public — চাইলে দেখাতেও পারবে।

Testing

Unit আর feature test?
Unit test একটা ছোট অংশ যাচাই করে, DB বা network ছাড়াই — তাই খুব দ্রুত চলে। Feature test পুরো পথটা দেখে, মানে route-এ request গেলে DB-তে ঠিক জিনিসটা বসল কিনা। আমি business-এর হিসাবগুলো unit-এ রাখি, আর গুরুত্বপূর্ণ flow গুলো feature-এ।
কী test করো?
যেখানে ভুল হলে ক্ষতি বেশি — টাকার হিসাব, permission, order-এর অবস্থা বদলানো। আর edge case গুলো। আমার একটা অভ্যাস আছে, যেকোনো bug fix করার সময় ওটার জন্য একটা test লিখে রাখি, যেন ওই একই bug আর কখনো ফিরে না আসে।
কী test করো না?
Framework নিজে যা করে সেটা না, যেমন Laravel-এর validation কাজ করে কিনা তা যাচাই করা অর্থহীন। Getter-setter-ও না। আর ১০০% coverage-এর পিছনে দৌড়াই না, কারণ coverage বেশি মানেই test ভাল না — কিছুই যাচাই করে না এমন test-ও coverage বাড়ায়।
Mock কখন করো?
যেগুলো আমার হাতের বাইরে — payment gateway, SMS, email, third-party API। ওগুলো সত্যি ডাকলে test ধীর হবে, খরচ হবে, আর ওদের server বন্ধ থাকলে আমার test fail করবে যদিও আমার code ঠিক আছে। নিজের code আমি mock করি না, তাহলে test আসলে কিছুই প্রমাণ করে না।
Test suite ধীর হয়ে গেলে?
DB প্রতিবার নতুন করে না বানিয়ে transaction দিয়ে rollback করি। Factory-তে দরকারের বেশি data বানাই না — একটা test-এর জন্য একশো row লাগে না। আর unit আর feature আলাদা করে চালাই, যেন দ্রুতগুলো আগে ফল দেয়।
"Test লিখে সত্যিই কী লাভ হয়েছে তোমার?" ← এই প্রশ্নটা তৈরি রাখো, এটাই তোমার সবচেয়ে শক্তিশালী উত্তর
আমার নিজের PHP framework-টায় প্রথমবার test suite চালিয়ে দুইটা সত্যিকারের bug বেরিয়েছিল, যেগুলো browser দিয়ে চালালে কখনো ধরা পড়ত না।

প্রথমটা — config file গুলো require_once দিয়ে load হচ্ছিল, কিন্তু ওই file গুলো আসলে একটা array return করে। require_once-এর নিয়ম হলো, দ্বিতীয়বার ডাকলে সে শুধু true ফেরত দেয়। তাই এক process-এ দ্বিতীয়বার application boot করলে config-এর জায়গায় true চলে আসত। ব্যবহারে কেউ ধরতে পারত না, কারণ একটা request-এ একবারই boot হয় — কিন্তু test একই process-এ বারবার boot করে, তাই সাথে সাথে ধরা পড়ল।

দ্বিতীয়টা — getallheaders() কোনো check ছাড়াই ডাকা ছিল। ওই function শুধু Apache আর FPM-এ থাকে, তাই command line থেকে চালালে framework-টা একদম fatal হয়ে যেত।

শিক্ষাটা হলো, test code-টাকে browser-এর বাইরে দিয়ে চালায় — তাই এমন জিনিস ধরে যা সাধারণ ব্যবহারে কখনো চোখে পড়ে না।
তোমার সব project-এ test আছে?
সৎভাবে বললে, না। আমার নিজের product গুলোতে test discipline আছে, কিন্তু client project-এ সময়ের চাপে সবসময় ছিল না। যেখানে ছিল সেখানে পার্থক্যটা স্পষ্ট দেখেছি, তাই নতুন কাজে আমি অন্তত গুরুত্বপূর্ণ flow গুলো ঢাকতে চাই। "সব জায়গায় test-first" বললে পরের প্রশ্নেই ধরা পড়বে। সৎ উত্তরটা এখানে বেশি নম্বর পায়।

DevOps

তোমাদের git workflow কেমন?
প্রতিটা কাজের জন্য আলাদা branch, তারপর PR দিয়ে merge — কেউ একজন দেখে দেয়। Commit ছোট রাখি আর message-এ কী করেছি স্পষ্ট লিখি, কারণ ছয় মাস পর ওটাই একমাত্র ব্যাখ্যা থাকে। Master সবসময় deploy করার মত অবস্থায় রাখি।
CI-তে কী চালাও?
Code style, static analysis, তারপর test। আমার নিজের framework-এ CI চারটা PHP version-এ আলাদা করে চালায়, 8.0 থেকে 8.3 — কারণ library হিসেবে ওটা সবগুলোতেই চলতে হবে, আর আমার একটা version-এ ঠিক থাকলেই হবে না। এইটা public repo, তাই বলার পর link দিতে পারবে। এই কারণেই কাজের CI-র বদলে এইটার কথা বলবে।
Zero-downtime deploy কীভাবে করো?
নতুন version আলাদা একটা folder-এ পুরো তৈরি করি — composer install, build, সব। তারপর একটা symlink ঘুরিয়ে নতুন folder-এ দিই; ওটাই সবচেয়ে জরুরি ধাপ, কারণ ওটা এক মুহূর্তে হয়ে যায়, মাঝখানে কোনো ভাঙা অবস্থা থাকে না। এরপর queue restart করি আর cache warm করি। কিছু ভুল হলে symlink আগের folder-এ ফিরিয়ে দিলেই rollback।
Deploy-এর সময় migration ভাঙে কেন?
Deploy-এর কয়েক সেকেন্ড পুরনো code আর নতুন DB একসাথে চলে। তাই আমি কাজটা ভেঙে ভেঙে করি — আগে নতুন column যোগ করি, তারপর code deploy করি, আর পুরনো column পরের release-এ drop করি। সরাসরি rename করা সবচেয়ে বিপজ্জনক, কারণ ওই মুহূর্তেই পুরনো code ভেঙে যায়।
Production-এ কিছু ভাঙলে কী করো?
আগে সাইট ঠিক করি, কারণ কারণ খুঁজতে বসলে user ততক্ষণ ভুগবে — তাই প্রথম কাজ rollback। তারপর log আর monitoring দেখে কারণ বের করি, fix করি, আর ওই জিনিসটার জন্য একটা test লিখে রাখি। শেষে দেখি একই ঘটনা আবার হওয়া আটকানোর কোনো ব্যবস্থা করা যায় কিনা। ক্রমটাই আসল উত্তর — আগে rollback, পরে তদন্ত। উল্টো বললে ওরা ধরে নেয় তুমি production সামলাওনি।
Docker কেন ব্যবহার করো?
সবার machine আর server একই রকম হয়ে যায়, তাই "আমার এখানে তো চলছিল" সমস্যাটা থাকে না। নতুন কেউ team-এ এলে প্রথম দিনেই project চালাতে পারে। একটা project-এ আমি পুরো Docker setup-টা সামলেছি, আর cron-এর আলাদা container-টা আমার নিজের লেখা।
Monitoring-এ কী দেখো?
Error rate, response time, queue-তে কত জমেছে, DB-র slow query log আর disk। আর এগুলোতে alert বসানো — alert না থাকলে আসলে user-ই আমার monitoring, আর ওটাই সবচেয়ে খারাপ অবস্থা।
Secret কোথায় রাখো?
Server-এর .env-এ, আর CI-তে ওদের নিজস্ব secret store-এ। Repo-তে কখনো না। এই ধরনের জিনিস আমি একবার ভুগে শিখেছি — একটা repo-তে ভুল git identity দিয়ে কয়েকটা commit হয়ে গিয়েছিল, push করার আগেই ধরে ঠিক করেছি। তারপর থেকে প্রতিটা repo-তে আলাদা করে local config দিয়ে দিই, global-এর উপর ভরসা করি না।

Behavioural + Salary

উত্তর দেবে STAR-এ — পরিস্থিতি, তোমার কাজ, সিদ্ধান্ত, ফল। প্রতিটা ২ মিনিট। "আমরা" না, "আমি" বলবে।

"নিজের সম্পর্কে বলুন"
আমি নয় বছর ধরে PHP আর Laravel-এ কাজ করছি, এখন DreamOnline-এ senior full-stack হিসেবে আছি। বেশিরভাগ কাজই বড় Laravel application — multi-tenant SaaS, payment integration, আর performance নিয়ে কাজ। এর বাইরে আমি নিজে একটা PHP framework লিখেছি, সেটাই framework গুলো ভিতর থেকে বুঝতে সবচেয়ে বেশি সাহায্য করেছে। এখন এমন একটা জায়গা খুঁজছি যেখানে architecture-এর সিদ্ধান্তে আরও বেশি দায়িত্ব নিতে পারব। নব্বই সেকেন্ড, এর বেশি না। মুখস্থ শোনানো যাবে না, কিন্তু আগে থেকে ঠিক করা থাকতেই হবে।
"চাকরি বদলাতে চাইছেন কেন?"
এখানে আমি অনেক কিছু শিখেছি আর বড় দায়িত্বও পেয়েছি। এখন আমি এমন কাজ চাই যেখানে scale আরও বড় আর architecture-এর সিদ্ধান্তে আমার ভূমিকা বেশি। বর্তমান employer-কে কখনো ছোট করবে না। করলে interviewer ধরে নেয় পরেরবার তুমি তাদের নিয়েও এভাবেই বলবে।
"আপনার সবচেয়ে বড় ভুল কী ছিল?"
একটা সত্যিকারের ভুল বলবে, সাজানো "আমি একটু বেশি পরিশ্রম করে ফেলি" ধরনের না। তোমার হাতে একটা ভাল উদাহরণ আছে — নিজের framework-এ config-এ debug মোড চালু অবস্থাতেই ship হয়ে যাচ্ছিল, publish করার ঠিক আগে ধরা পড়ে। ভুলটা সোজাসুজি বলো, তারপর বলো তুমি কী বদলেছ — publish-এর আগে একটা checklist আর test যোগ করা। শেষ অংশটাই আসল উত্তর। ওরা ভুল শুনতে চায় না, ভুলের পর তুমি কী করো সেটা শুনতে চায়।
"Lead-এর সাথে দ্বিমত হলে কী করেন?"
আমি কারণটা গুছিয়ে জানাই — কেন এই পথটা ঝুঁকিপূর্ণ মনে হচ্ছে, সম্ভব হলে data বা উদাহরণ সহ। এরপর সিদ্ধান্ত উনার, আর সিদ্ধান্ত হয়ে গেলে আমি সেটা পুরো মন দিয়ে করি। যেটা করি না সেটা হলো চুপচাপ অন্যভাবে কাজ করে ফেলা।
"Junior দের কীভাবে সামলান?"
Hellotask-এ আমি চারজনের একটা team চালিয়েছি — architecture আর planning আমার হাতে ছিল, দুইজন junior আমার সাথে কাজ করত, deploy-ও আমি করতাম। Junior দের কাজ আমি ছোট ছোট ভাগে দিতাম যেন কেউ তিন দিন আটকে না থাকে। আর code review-তে শুধু "এটা বদলাও" লিখতাম না, কেন বদলাতে হবে সেটা বলতাম — নাহলে পরেরবার একই ভুল আসে।
"চাপের মধ্যে কীভাবে কাজ করেন?"
আমি আগে ঠিক করি কোনটা না হলেই চলবে না আর কোনটা পরে হলেও চলে, তারপর সেটা team আর stakeholder-কে জানিয়ে দিই। চুপচাপ সব করার চেষ্টা করে শেষ দিনে ব্যর্থ হওয়ার চেয়ে আগেই বলে দেওয়া ভাল। এর সাথে তোমার নিজের একটা সত্যি deadline-এর ঘটনা জুড়ে দাও — বিশেষ করে কী কেটে বাদ দিয়েছিলে সেটা। Scope কাটতে পারা senior-এর লক্ষণ।
"আপনি কি শুধু Laravel-ই পারেন?"
না। Python-এ আমি একটা real-time telemetry service বানিয়েছি — FastAPI, MQTT আর WebSocket দিয়ে, চারজনের একটা team lead করে। Node-এ একটা WebRTC ভিত্তিক online classroom করেছি। আর PHP-তে নিজের framework তো আছেই। Laravel আমার মূল জায়গা, কিন্তু নতুন stack ধরতে আমার সমস্যা হয় না। ⚠️ ওই Python project-এর client কে বা কী কাজে ব্যবহার হয় — কোনোটাই বলবে না। শুধু কী বানিয়েছ আর কী প্রযুক্তি, ওখানেই থামবে।

⚠ Salary — এইখানে ভুল করলে বাকি প্রস্তুতি বৃথা

  • তোমার floor (১ লাখ) কখনো expectation হিসেবে বলবে না। যেই সংখ্যা তুমি বলবে, ওটাই ছাদ হয়ে যায় — কেউ তার উপরে দেয় না।
  • ৯ বছর, Zend certification আর দুইবার team lead — ঢাকায় ১ লাখ একজন ভাল mid-level engineer-কে বলা হয়।
  • খুলবে ১.৪ থেকে ১.৮ লাখ range দিয়ে, তারপর বলবে "role আর responsibility দেখে আলোচনা করা যেতে পারে"।
  • চেষ্টা করবে ওরা আগে বলুক — "এই position-এর জন্য আপনাদের budget range টা জানতে পারি?"

⚠ Notice period — "immediate" লিখিতভাবে দেওয়ার আগে নিজের contract একবার দেখে নাও। বলার পর মিলল না, সেটা খারাপ দেখায়।

১০ Story bank — ১০টা গল্প

এই দশটা তৈরি থাকলে প্রায় সব behavioural আর "আপনি কী করেছেন" প্রশ্ন কভার হয়ে যায়। প্রতিটা ২ মিনিটে, সংখ্যা সহ বলার practice করো।

#গল্পকোন প্রশ্নে লাগবে
নিজের PHP framework — container, auth, migration engine, console command"গভীরতা আছে?" · "framework ভিতরে কীভাবে কাজ করে?"
Test চালিয়ে দুইটা আসল bug ধরা (§৭)"test করে লাভ কী?" · quality
Query ২০ সেকেন্ড থেকে ৩০০ মিলিসেকেন্ড"performance সমস্যা solve করেছেন?"
Multi-tenant SaaS, per-tenant cache invalidationscale · architecture
Subscription tier — interface আর handler দিয়ে, if-else দিয়ে নাSOLID · "নতুন plan যোগ করা কত সহজ?"
Apple আর Google login শূন্য থেকে"কঠিন integration করেছেন?"
সরকারি NID / KYC verificationthird-party integration · ঢাকায় খুব কম লোক পেরেছে
Hellotask-এ ৪ জনের team lead, deploy সহleadership
Python + MQTT + WebSocket real-time service"শুধু Laravel পারেন?"
১০Dependency advisory-তে CI লাল, version তুলে সমাধানsecurity · CI/CD

⚠ গল্প বলার দুইটা নিয়ম

  • Client-এর নাম বলবে না — কাজের ধরনটা বলো, যেমন "একটা জাপানি fitness operator-এর জন্য"।
  • Python service-টার client বা উদ্দেশ্য কোনোটাই বলবে না — শুধু কী বানিয়েছ, কী প্রযুক্তি, আর কয়জনের team।

১১ তুমি কী প্রশ্ন করবে

শেষে জিজ্ঞেস করবে "আপনার কোনো প্রশ্ন আছে?" — "না" বললে নম্বর কাটা যায়। তিনটা তৈরি রাখো।

  • Team কত বড়, আর আমি কার কাছে report করব?
  • Code review আর deploy কীভাবে হয় — সপ্তাহে কতবার deploy হয়?
  • এই role-এ ছয় মাস পর "সফল" বলতে আপনারা কী বুঝবেন?
  • কাজটা বেশিরভাগ পুরনো code maintain করা, না নতুন কিছু বানানো?
  • Position-টা কেন খালি — নতুন তৈরি হয়েছে, না কেউ ছেড়ে গেছেন?

১২ শেষ ২৪ ঘণ্টার checklist

  • নিজের CV পুরোটা পড়ো — প্রতিটা লাইনে ভাবো "এটা নিয়ে কী প্রশ্ন করতে পারে?"
  • JD আবার পড়ো, পাঁচটা keyword দাগাও
  • Company-র site আর product একবার দেখো
  • §১০ থেকে তিনটা গল্প জোরে বলো
  • §৫-এর সাত ধাপ একবার চোখ বুলাও
  • Salary-র লাইনটা মুখস্থ করো (§৯)
  • ওদের জন্য দুইটা প্রশ্ন লিখে রাখো
  • Laptop, internet, ঘর আর আলো — আগের রাতেই দেখে নাও
  • ঘুমাও। ক্লান্ত মাথায় system design হয় না।