Module 1 — Thinking Like a Backend Engineer

Lesson 1 — What Makes Backend Engineering Advanced?

ReadingPreview

You are viewing a free preview lesson.

একটি backend application বানানো তুলনামূলকভাবে সহজ।

কিন্তু এমন একটি backend system বানানো, যা traffic বাড়লেও, dependency fail করলেও, একই data নিয়ে concurrent operation হলেও, requirement বদলালেও, এবং বহু engineer একসাথে কাজ করলেও নির্ভরযোগ্য থাকে — সেটাই কঠিন।

এই জায়গা থেকেই Advanced Backend Engineering শুরু হয়।

Advanced Backend Engineering মানে শুধু আরও বেশি framework, library বা infrastructure tool জানা নয়।

মূল বিষয় হলো:

একটি system কীভাবে behave করবে, কোথায় fail করতে পারে, কীভাবে evolve করবে, এবং কোন trade-off গ্রহণযোগ্য — তা বুঝে design করা।


এই Lesson শেষে আপনি যা বুঝবেন

এই lesson শেষে আপনি বুঝতে পারবেন:

  • সাধারণ backend development এবং advanced backend engineering-এর পার্থক্য;
  • কেন working code মানেই correct system নয়;
  • scale কীভাবে নতুন সমস্যা তৈরি করে;
  • failure কেন production system-এর normal অংশ;
  • concurrency কীভাবে seemingly-correct code ভেঙে দিতে পারে;
  • system evolve করার সময় কেন compatibility গুরুত্বপূর্ণ;
  • team structure কীভাবে architecture-এ প্রভাব ফেলে;
  • কেন architecture মূলত trade-off management।

1. Feature বানানো আর System Engineer করা এক জিনিস নয়

ধরি requirement খুব সাধারণ:

একজন customer একটি order তৈরি করতে পারবে।

একটি basic implementation হতে পারে:

Client
  │
  ▼
OrderController
  │
  ▼
OrderService
  │
  ▼
OrderRepository
  │
  ▼
PostgreSQL

Request:

POST /orders

Application request validate করল, order তৈরি করল, database-এ save করল, তারপর response দিল।

Feature কাজ করছে।

কিন্তু production-এ কিছু প্রশ্ন চলে আসে:

  • একই request দুইবার এলে কী হবে?
  • order তৈরি হয়ে গেলে, কিন্তু client response না পেলে কী হবে?
  • client retry করলে duplicate order হবে কি?
  • দুইজন customer একই সময়ে শেষ item কিনতে চাইলে কী হবে?
  • database slow হলে কী হবে?
  • payment succeed করল কিন্তু inventory fail করলে কী হবে?
  • traffic 100 RPS থেকে 10,000 RPS হলে কী হবে?
  • system unhealthy হলে আমরা জানব কীভাবে?
  • database schema change করলে পুরোনো application instance break করবে কি?

এগুলো controller বা annotation-এর প্রশ্ন নয়।

এগুলো system engineering-এর প্রশ্ন।


2. Working Code মানেই Correct System নয়

ধরি আমাদের endpoint:

POST /orders

Request:

{
  "productId": "P123",
  "quantity": 1
}

Server একটি order তৈরি করল:

{
  "orderId": "O456",
  "status": "CREATED"
}

এখন sequenceটা এমন হলো:

Client
   │
   │ POST /orders
   ▼
Server
   │
   ├── Order তৈরি হলো
   │
   ├── Response পাঠানো হলো
   │
   X Network connection lost

Server-এর perspective থেকে operation সফল।

কিন্তু client response পায়নি।

Client জানে না:

Order তৈরি হয়েছে?
নাকি request fail করেছে?

তাই client retry করল।

POST /orders

Server আবার নতুন order তৈরি করতে পারে।

এখন দুইটি request-ই technically successful।

কিন্তু business result ভুল:

Expected order = 1

Actual order = 2

এখান থেকে একটি গুরুত্বপূর্ণ principle পাই:

Request-level correctness আর business-level correctness এক জিনিস নয়।

পরে আমরা idempotency দিয়ে এই ধরনের সমস্যা কীভাবে solve করতে হয় তা শিখব।

এই lesson-এ লক্ষ্য শুধু problem চিনতে শেখা।


3. Scale Complexity তৈরি করে

ধরি প্রথমে application receive করছে:

10 requests/second

Architecture:

Client
  │
  ▼
Application
  │
  ▼
PostgreSQL

এটা সহজেই কাজ করতে পারে।

এরপর traffic হলো:

1,000 requests/second

তারপর:

10,000 requests/second

এখন আগে যেসব বিষয় গুরুত্বহীন মনে হতো, সেগুলো problem হয়ে দাঁড়াতে পারে।

যেমন:

  • slow SQL query;
  • missing index;
  • বেশি database connection;
  • unnecessary network call;
  • CPU-heavy processing;
  • synchronous operation;
  • large response;
  • memory pressure;
  • hot database row।

একটি common solution হতে পারে application instance বাড়ানো:

                   Load Balancer
                        │
          ┌─────────────┼─────────────┐
          ▼             ▼             ▼
       API #1         API #2        API #3
          │             │             │
          └─────────────┼─────────────┘
                        ▼
                   PostgreSQL

Application layer scale করল।

কিন্তু এখন তিনটি instance একসাথে database-এ বেশি connection খুলছে।

Result:

Application bottleneck কমলো

কিন্তু

Database bottleneck তৈরি হলো

এখানে মূল lesson হলো:

একটি component scale করলেই পুরো system scale হয় না।

System-কে end-to-end বুঝতে হয়।


4. Failure Production System-এর স্বাভাবিক অংশ

Production system-এ failure exception নয়।

Failure expected।

উদাহরণ:

  • network timeout;
  • database slow;
  • application restart;
  • container terminate;
  • DNS failure;
  • external API unavailable;
  • message duplicate delivery;
  • connection reset।

ধরি flow:

Order Service
      │
      ▼
Payment Service
      │
      ▼
Inventory Service

Payment succeed করেছে।

Inventory fail করেছে।

এখন কী হবে?

Possible options:

Payment refund করা

Inventory retry করা

Order pending রাখা

Order cancel করা

Manual review-এ পাঠানো

কোনটা correct?

একটা universal answer নেই।

Business context-এর উপর depend করবে।

এই জন্য:

Failure handling architecture-এর অংশ।

Failure handling পরে add করা optional feature নয়।


5. Concurrency Correct Code-ও ভেঙে দিতে পারে

ধরি inventory table:

product_id | available_quantity
-----------|-------------------
P123       | 1

একটি item বাকি।

দুইজন customer একই সময়ে কিনতে চাইল।

Request A read করল:

available_quantity = 1

Request B-ও read করল:

available_quantity = 1

দুইজনই মনে করল item available।

Code:

if (product.getAvailableQuantity() > 0) {
    product.decreaseQuantity();
    repository.save(product);
}

Single request দিয়ে দেখলে code ঠিক।

কিন্তু দুইটি request parallel run করলে সমস্যা হতে পারে।

এটাই concurrency-এর challenge।

Sequentially correct code concurrently incorrect হতে পারে।

পরে আমরা শিখব:

  • transactions;
  • isolation levels;
  • optimistic locking;
  • pessimistic locking।

এখন শুধু problemটা চিনে রাখুন।


6. Backend System মূলত State নিয়ে কাজ করে

Backend system সাধারণত state manage করে।

যেমন:

  • order;
  • payment;
  • inventory;
  • account balance;
  • subscription;
  • identity;
  • permissions।

এই state ভুল হলে system outwardly healthy দেখালেও business broken হতে পারে।

উদাহরণ:

Expected balance = €100

Actual balance = €150

Server চলছে।

CPU normal।

API 200 OK দিচ্ছে।

তবুও system incorrect।

তাই backend engineer-এর responsibility শুধু:

"API চলছে কি?"

না।

বরং:

"System-এর state correct আছে কি?"

এটাই বড় প্রশ্ন।


7. Time-এর সাথে System আরও Complex হয়

Production system static নয়।

System evolve করে।

ধরি প্রথম version API return করে:

{
  "id": "123",
  "name": "Laptop"
}

নতুন requirement অনুযায়ী আমরা চাই:

{
  "id": "123",
  "displayName": "Laptop"
}

Simple rename মনে হচ্ছে।

কিন্তু problem:

  • অন্য service এখনো name expect করছে;
  • mobile app-এর পুরোনো version name expect করছে;
  • Kafka-তে পুরোনো event আছে;
  • background worker old schema use করছে।

এই কারণে production system-এ গুরুত্বপূর্ণ হয়ে যায়:

Backward compatibility
Schema evolution
Migration
Deprecation
Rollback
Deployment order

Architecture শুধু final state design নয়।

Architecture হলো:

আজকের system থেকে আগামী দিনের system-এ safely যাওয়া।


8. Team বড় হলে Architecture-এর গুরুত্ব বাড়ে

একজন engineer পুরো application maintain করলে coordination সহজ।

কিন্তু ধরুন organisation-এ আছে:

Accounts Team
Catalog Team
Orders Team
Payments Team
Inventory Team
Shipping Team

এখন Orders team যদি event format change করে:

Orders change
     ↓
Inventory break

Payments API change করলে:

Payments change
      ↓
Checkout break

যদি সবাই সবার database directly access করে, ownership unclear হয়ে যায়।

Architecture এখানে সাহায্য করে define করতে:

  • কে কোন system-এর owner;
  • কোন data কে manage করবে;
  • কোন interface stable;
  • কোথায় dependency allowed;
  • কোন team independently deploy করতে পারবে।

তাই architecture শুধু software নিয়ে নয়।

Architecture organisational structure-এর সাথেও সম্পর্কিত।


9. Advanced Engineer Technology দিয়ে শুরু করে না

Common question:

কোন database সবচেয়ে ভালো?

Better question:

এই workload-এর requirement কী?

Database choose করার আগে প্রশ্ন করা উচিত:

Transaction দরকার কি?

Durability কতটা গুরুত্বপূর্ণ?

Access pattern কেমন?

কত data হবে?

Read বেশি নাকি write বেশি?

Stale data acceptable কি?

Latency target কত?

Operational complexity কতটা গ্রহণযোগ্য?

একইভাবে:

Kafka
Redis
Microservices
Kubernetes
Temporal
NoSQL

এসব দিয়ে শুরু করা উচিত নয়।

প্রথমে requirement।

তারপর technology।

Technology should follow requirements.


10. প্রতিটি Solution নতুন Problem আনে

ধরি database read slow।

আমরা Redis add করলাম।

Before:

Application
     │
     ▼
PostgreSQL

After:

Application
     │
     ▼
   Redis
     │
 Cache miss
     ▼
PostgreSQL

Latency improve করল।

কিন্তু এখন নতুন problem:

PostgreSQL-এ:

Price = €100

Redis-এ:

Price = €90

তাহলে কোনটা correct?

আমরা solve করেছি:

Performance

কিন্তু introduce করেছি:

Consistency problem

এটাই advanced backend engineering-এর recurring pattern:

একটি problem solve করলে প্রায়ই নতুন trade-off তৈরি হয়।


11. Microservices সবসময় Better নয়

Microservices কিছু advantage দিতে পারে:

  • independent deployment;
  • team ownership;
  • separate scaling;
  • domain separation।

কিন্তু এর cost:

  • network failure;
  • distributed transactions;
  • operational overhead;
  • observability complexity;
  • deployment complexity;
  • cross-service debugging।

তাই:

Microservices ব্যবহার করলেই architecture advanced হয়ে যায় না।

অনেক ক্ষেত্রে modular monolith-ই better engineering decision।

Advanced engineering মানে complex solution choose করা নয়।

Appropriate solution choose করা।


12. Architecture মানে Trade-Off Management

একজন engineer বলল:

Kafka use করি, কারণ Kafka scalable।

এটা weak reasoning।

Better reasoning:

আমাদের durable event retention, replay, partition-level ordering এবং multiple independent consumer দরকার। Kafka এই requirementগুলো satisfy করে, তবে এর সাথে infrastructure এবং operational complexity বাড়বে।

এখানে দুই দিকই আছে:

Benefit
+
Cost

এটাই architectural thinking।

Question হওয়া উচিত না:

Kafka ভালো কি?

বরং:

Kafka কোন problem solve করছে এবং এর বিনিময়ে আমরা কী complexity নিচ্ছি?


13. Production-এ "Done" এর Definition বদলে যায়

Simple application-এ:

✓ Code works
✓ Test passes
✓ API responds

Production system-এ:

✓ Functional requirement works

✓ Concurrent operation safe

✓ Retry safe

✓ Failure behavior defined

✓ Useful logging আছে

✓ Metrics আছে

✓ Deployment safe

✓ Rollback possible

✓ Database migration compatible

✓ Capacity understood

এই জন্য production readiness শুধু code-এর property নয়।

এটা পুরো system-এর property।


14. Backend Engineer-এর Mental Checklist

এই course জুড়ে আমরা বারবার কিছু প্রশ্ন করব।

Correctness

এই operation invalid business state তৈরি করতে পারে কি?

Failure

Dependency fail করলে কী হবে?

Concurrency

একই operation একসাথে run করলে কী হবে?

Scale

Traffic 100× হলে কী হবে?

Data

Source of truth কোথায়?

Consistency

Data কতটা stale হতে পারে?

Recovery

Partial failure থেকে system recover করতে পারবে?

Observability

System broken হলে আমরা জানব কীভাবে?

Evolution

এই change পুরোনো consumer break করবে কি?

Operations

Incident হলে অন্য engineer বুঝতে পারবে কী ঘটছে?

এই প্রশ্নগুলো advanced backend engineer-এর core habit।


Practical Exercise — Simple Order System

Architecture:

Client
  │
  ▼
Order API
  │
  ▼
PostgreSQL

Endpoint:

POST /orders

Request:

{
  "productId": "P123",
  "quantity": 1
}

Application:

1. Inventory check করে
2. Order তৈরি করে
3. Inventory কমায়
4. Order return করে

Current traffic:

100 requests/second

এখন নিচের scenarioগুলো analyse করুন।


Scenario 1 — Concurrent Purchase

দুইজন customer একই সময়ে শেষ item কিনতে চায়।

ভাবুন:

কী ভুল হতে পারে?

Solution এখন দরকার নেই।

Problem identify করুন।


Scenario 2 — Client Retry

Order successfully তৈরি হয়েছে।

কিন্তু response client-এর কাছে পৌঁছেনি।

Client retry করল।

প্রশ্ন:

কী ধরনের incorrect business state তৈরি হতে পারে?

Scenario 3 — Slow Database

Normally query latency:

20 ms

হঠাৎ হলো:

5 seconds

ভাবুন:

  • request-এর কী হবে?
  • application resource-এর কী হবে?
  • user experience কীভাবে affect হবে?

Scenario 4 — Traffic Spike

Traffic:

100 RPS

থেকে:

10,000 RPS

হলো।

কোন কোন component bottleneck হতে পারে?

Technology solution না দিয়ে আগে problem identify করুন।


Scenario 5 — Redis যোগ করা হলো

Database load কমানোর জন্য Redis add করা হলো।

এখন ভাবুন:

কী ধরনের নতুন consistency problem আসতে পারে?

Exercise Format

প্রতিটি scenario-এর জন্য তিনটি প্রশ্নের উত্তর দিন:

1. কী fail করতে পারে?

2. Business impact কী হতে পারে?

3. Solution choose করার আগে কী information দরকার?

এই exercise-এর উদ্দেশ্য technology select করা নয়।

উদ্দেশ্য:

Solution-এর আগে problem বুঝতে শেখা।


Key Takeaways

এই lesson থেকে সবচেয়ে গুরুত্বপূর্ণ বিষয়গুলো:

1. Working code যথেষ্ট নয়

System-কে failure, retry, concurrency এবং change-এর মধ্যেও correct থাকতে হবে।

2. Scale assumption বদলে দেয়

100 RPS-এ যে architecture কাজ করে, 100,000 RPS-এ সেটি কাজ নাও করতে পারে।

3. Failure normal

Production system design করতে হবে failure ধরে নিয়ে।

4. Concurrency dangerous

Sequentially correct code parallel execution-এ incorrect হতে পারে।

5. System evolve করে

Backward compatibility এবং migration খুব গুরুত্বপূর্ণ।

6. Architecture team structure-এর সাথেও সম্পর্কিত

Ownership এবং dependency design-এর অংশ।

7. প্রতিটি solution-এর cost আছে

Redis, Kafka, microservices — সবকিছু problem solve করে, আবার নতুন complexity আনে।

8. Architecture মানে trade-off

সঠিক প্রশ্ন:

কোন technology সবচেয়ে ভালো?

না।

সঠিক প্রশ্ন:

আমাদের requirement-এর জন্য কোন trade-off সবচেয়ে গ্রহণযোগ্য?


Next Lesson

Lesson 2 — Understanding the Request Lifecycle

পরের lesson-এ আমরা একটি request-এর পুরো journey দেখব:

Client
  ↓
Load Balancer
  ↓
Application
  ↓
Cache
  ↓
Database
  ↓
External Dependencies

আমরা বুঝব:

  • latency কোথায় তৈরি হয়;
  • কোন layer-এ failure হতে পারে;
  • কোন resource কোথায় consume হয়;
  • এবং backend optimize করার আগে complete request lifecycle বোঝা কেন জরুরি।