<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Monirul Islam</title>
    <description>The latest articles on DEV Community by Monirul Islam (@mislam-dev).</description>
    <link>https://dev.to/mislam-dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F914471%2Fb32f9d03-cedb-4d6e-9d36-c7d36b7ff0cd.JPG</url>
      <title>DEV Community: Monirul Islam</title>
      <link>https://dev.to/mislam-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mislam-dev"/>
    <language>en</language>
    <item>
      <title>Day 29 — Observability: Logs, Metrics, Traces — Production-এর তিন চোখ</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Sun, 04 Oct 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-29-observability-logs-metrics-traces-production-er-tin-cokh-3h07</link>
      <guid>https://dev.to/mislam-dev/day-29-observability-logs-metrics-traces-production-er-tin-cokh-3h07</guid>
      <description>&lt;p&gt;আপনার application এখন আরামে চলছে। Engineering team-ও একটু শান্তিতে আছে। এখন আর তাদের বেশি প্যারা নিতে হচ্ছে না। এত কিছু হওয়ার পরেও একটা জিনিস বাকি রয়ে গেছে। আপনার application-এর বয়স অনেক দিন হয়ে গেল। কিন্তু আপনাকে যদি জিজ্ঞেস করা হয় গত ১ মাসে আপনার application-এর user-এর সংখ্যা কেমন ছিল, বা ৭ দিনের? এই প্রশ্নের উত্তর আপনি এখন শুধু অনুমান করে বলতে পারবেন। Exactly কোনো data নেই।&lt;/p&gt;

&lt;p&gt;আপনি এখন microservice architecture-এ আছেন। এখন অনেকগুলো server হয়ে গেছে। একটা service-এর জন্য multiple region-এ multiple server রয়েছে। এই serverগুলো কখন কী হচ্ছে, কোন server-এর জন্য usage কেমন, তাদের uptime record কেমন, কোনো error face করছে কিনা—এগুলো কিন্তু real-time-এ দেখার কোনো ব্যবস্থা আপনার কাছে নেই।&lt;/p&gt;

&lt;p&gt;আরেকটা situation বলি, আপনার engineering team খুব ভালো ভাবে testing করেছে + test case লিখে রেখেছে, সেগুলো test হয়েছে। CI/CD pipeline-এ হয়েছে। এ ছাড়াও একটা systematic way-তে engineering team এমন ব্যবস্থা করেছে যে, যাই হয়ে যাক application-এ কোনো error হলে server crash করবে না। কিন্তু testing environment আর production—২টা জিনিস একেবারেই আলাদা। কখন কোন সময় কী issue হবে আপনি বলতে পারবেন না। For example, এমন একটা error হলো (rare error), error যেহেতু handle হয়েছে সেহেতু server crash করবে না। আর আপনিও বুঝতে পারবেন না যে কোনো error হয়েছে। আর আপনি বুঝতে না পারলে error solve হবে না। একটা সময় এই error-ই আপনার system crash-এর কারণ হয়ে যেতে পারে। এখন প্রশ্ন হচ্ছে এটা কীভাবে prevent করবেন?&lt;/p&gt;

&lt;p&gt;এই situation handle করার জন্য মূলত ময়দানে আসে &lt;strong&gt;Observability&lt;/strong&gt;। এর মাধ্যমে আপনার application-এর যাবতীয় information real-time-েই দেখতে পারবেন।&lt;/p&gt;




&lt;h2&gt;
  
  
  Observability-র তিনটা Pillar
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Logs
&lt;/h3&gt;

&lt;p&gt;একটা জিনিস খেয়াল করবেন, বড় building + office-এর gate-এ একজন guard থাকেন যিনি building-এ কে entry নিচ্ছে আর কে building থেকে বাইরে যাচ্ছে সব কিছুর record রাখছেন। এইটা রাখার মূল কারণ হচ্ছে যদি কোনো incident হয় তাহলে এটা helpful হবে। এই entryগুলোই হচ্ছে logs।&lt;/p&gt;

&lt;p&gt;Similar way-তে application-এ কে access করছে, কী access করছে, তাকে কী response দেওয়া হয়েছে, কোনো error হয়েছে কিনা, কী error হয়েছে—এই সবকটি জিনিস store করে রাখা হয় যাতে পরে এগুলো analysis করা যায়।&lt;/p&gt;

&lt;p&gt;মূলত এই logs-এর মাধ্যমেই application level error + bug-এর solution করা হয়ে থাকে। অনেক ক্ষেত্রে infrastructure related errorগুলোও এই logs analysis করার মাধ্যমে বের করা যায়।&lt;/p&gt;

&lt;h3&gt;
  
  
  Metrics
&lt;/h3&gt;

&lt;p&gt;এইটা log-এর মতোই, তবে এটা infrastructure level-এ কাজ করে। যেমন সার্ভার কতগুলো, তাদের CPU, memory usage কেমন, তারা কেমন user serve করছে, তাদের health কেমন, কোনো fault আছে কিনা—এই সব কিছু metrics-এর মাধ্যমে বের করা যায়।&lt;/p&gt;

&lt;h3&gt;
  
  
  Traces
&lt;/h3&gt;

&lt;p&gt;একটা গল্প বলি, আপনি নিশ্চয়ই কোনো গুপ্তধন খোঁজার রহস্যের গল্প পড়েছেন অথবা movies-এ দেখেছেন। ওখানে একটা জিনিস খেয়াল করবেন যে একটা ছোট information decode করে step-by-step ওই গুপ্তধনের কাছে পৌঁছে যায়। এই যে step-by-step, একটা জিনিস থেকে অন্য একটা জিনিসে যাওয়ার history-টাই হচ্ছে traces।&lt;/p&gt;

&lt;p&gt;অনেক সময় application-এ কোনো একটা request কোন layer (services) হয়ে গেছে তা জানার প্রয়োজন হয়। এই জন্য প্রতিটা request-এর history store করার প্রয়োজন হয়। Tracing-টা সব থেকে বেশি কাজে লাগে যখন কোনো error হয়। একটা error আসলে কোনো service-এর কোনো file-এর কারণে হয়েছে তা এই tracing-এর মাধ্যমে easily identify করা যায়।&lt;/p&gt;




&lt;h2&gt;
  
  
  Structured Logging
&lt;/h2&gt;

&lt;p&gt;অগোছালো জিনিস নিয়ে কাজ করা একটু ঝামেলার, process করতে অনেক problem face করা লাগে + output properly generate করা possible না। এখন আপনি যদি logsগুলো অগোছালোভাবে store করেন তাহলে সেখান থেকে data output generate করা tough। এই জন্য structured way-তে log store করা দরকার। এই structured dataগুলো সব predictable, এই জন্য আপনি চাইলেই processing-এর জন্য একটা program লিখে রাখতে পারেন।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ এটা search করা কঠিন&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`User 5 placed order 123 at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ এটা search, filter, aggregate করা যায়&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Order placed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-request-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Structured log মানেই হচ্ছে JSON। JSON data-এর ওপর easily query করা যায়।&lt;/p&gt;

&lt;p&gt;Logging-এর জন্য অনেক ধরনের tool আছে, for example: Elasticsearch, CloudWatch, Loki ইত্যাদি। এগুলো dynamically আপনার করা logsগুলো store করে সেখান থেকে process করবে। এই সব toolগুলো default ভাবেই JSON data parse করতে পারে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Log Levels
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Alert দরকার&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;High memory usage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;85%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// নজরে রাখো&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Order created&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Normal flow&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cache miss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Dev only&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log level-টা error বা bug resolve করার জন্য খুবই কাজে লাগে। একটা application যেখানে ১ মিলিয়ন user আছে সেখানে যদি সব log-ই সেম থাকে তাহলে আপনাকে error খুঁজতে বেগ পেতে হবে। আর logging toolগুলো কিছুই করতে পারবে না।&lt;/p&gt;

&lt;p&gt;Suppose আপনি application-এ কী কী error encounter হয়েছে সেগুলো দেখতে চাচ্ছেন, তখন আপনি just error log level দিয়ে filter করলেই error related সবগুলো পেয়ে যাবেন। Proper way-তে log level maintain করলে log analysis করা easy হয়ে যায়।&lt;/p&gt;

&lt;p&gt;একটা জিনিস, debug level-টা শুধুমাত্র dev environment-এর জন্য use করবেন। Production-এ যেন এই debug level-টা off করা থাকে, না হয় অনেক unnecessary log store হয়ে যাবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Metrics
&lt;/h2&gt;

&lt;p&gt;Production-এ CPU, memory, response time, active user count — এই সংখ্যাগুলো সবসময় monitoring-এর মধ্যে রাখা হয়।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Prometheus metrics&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpRequestDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Histogram&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http_request_duration_seconds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;help&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HTTP request duration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;labelNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;route&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status_code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dashboard-এ দেখতে পাবেন —&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;প্রতি সেকেন্ডে কতটা request আসছে&lt;/li&gt;
&lt;li&gt;Average response time&lt;/li&gt;
&lt;li&gt;Error rate&lt;/li&gt;
&lt;li&gt;DB connection pool usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grafana + Prometheus use করে এই টাইপের dashboard easily বানানো যায়। In fact অনেক existing template আছে, চাইলে সেগুলোও use করা যেতে পারে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Distributed Tracing: Request-এর পুরো যাত্রা
&lt;/h2&gt;

&lt;p&gt;এই জিনিসটা একটা Nightmare। আপনি যখন Microservices Architecture + Multiple region-এ support দেন তখন by default "API Gateway", "Load Balancer" এই জিনিসগুলো চলে আসে। Similar type-এর অনেক জিনিসপত্র এখানে use হওয়াটা নরমাল ব্যাপার। একটা request কোথায় কোথায় যাচ্ছে, কোন কোন layer দিয়ে যাচ্ছে, কত time নিচ্ছে—এই জিনিসগুলোর trace রাখাটা দরকার। System optimize করার ক্ষেত্রে এগুলো কাজে লাগে।&lt;/p&gt;

&lt;p&gt;For example, আপনার application-এর জন্য Asia + Europe, দুই জায়গায় server আছে। কিন্তু Asia থেকে request গেলে তার latency অনেক বেশি হচ্ছে, কিন্তু Europe-এর টা ঠিকই আছে। এই ক্ষেত্রে আপনি কীভাবে বিষয়টাকে deal করবেন?&lt;/p&gt;

&lt;p&gt;এই distributed tracing-এর মাধ্যমে আপনি জানতে পারেন, Asia থেকে যে requestগুলো যাচ্ছে সেগুলো সব America-তে থাকা server থেকে response আসছে। আরেকটু analysis করার পরে বুঝতে পারলেন যে load balancer এই কাজটা করছে। এখন আপনি কিন্তু latency বেশি হওয়ার reason-টা জানেন। এই problem solve করা আপনার জন্য খুব বেশি problem হবে না।&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard Tool: OpenTelemetry (OTel)
&lt;/h3&gt;

&lt;p&gt;Distributed Tracing implementation জন্য বর্তমান industry gold standard হলো &lt;strong&gt;OpenTelemetry (OTel)&lt;/strong&gt;।&lt;/p&gt;

&lt;p&gt;আগে ডেটা কালেক্ট করার জন্য একেক টুলের (Datadog, New Relic, Jaeger) আলাদা আলাদা লাইব্রেরি দিয়ে কোড instrument করতে হতো, যার ফলে অন্য কোনো vendor switch করা অত্যন্ত কঠিন ছিল (Vendor Lock-in)।&lt;/p&gt;

&lt;p&gt;OpenTelemetry এই সমস্যার সমাধান করে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vendor-Neutral:&lt;/strong&gt; কোডে একবার OTel SDK দিয়ে trace/metrics/logs বসাবেন, এরপর কনফিগারেশন চেঞ্জ করে Jaeger, Prometheus বা যেকোনো cloud provider-এ পাঠাতে পারবেন; কোড পরিবর্তন করতে হবে না।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Propagation:&lt;/strong&gt; microservice-এর একটি service যখন অন্য service-কে কল করে তখন OTel automatically HTTP হেডার দিয়ে &lt;code&gt;traceparent&lt;/code&gt; (Trace ID এবং Span ID) পাস করে দেয়। ফলে পুরো request journey-এর প্রতিটি স্টেপ একটি একক সূত্রে গেঁথে যায়।&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Alerting: ঘুম থেকে তুলবে
&lt;/h2&gt;

&lt;p&gt;ছোটবেলায় যখন কোনো মিশন (আপনি জানেন কী mean করছি) করতে যেতাম, তখন ১ জনকে পাহারা দিতে বলতাম। তাকে বলা ছিল যে, যদি কেউ ধারের কাছে আসে তাহলে আমাদেরকে একটা sound দিয়ে জানিয়ে দিবি, আমরা safe zone-এ চলে যাব। আসলে ওই ১ জন ছিল আমাদের alerting system।&lt;/p&gt;

&lt;p&gt;Application-এর ক্ষেত্রে এই alerting প্রয়োজন। এই alerting system-এর threshold set করা রাখতে হবে আর সেটা check হবে metrics-এর মাধ্যমে। Threshold cross করলেই alert দেবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;Production system মানে অন্ধকারে কাজ না। Logs, Metrics, Traces — এই তিনটা ঠিকঠাক থাকলে যেকোনো incident দ্রুত diagnose করা যায়। Observability-তে invest করা কোনো luxury না। এটা professional software engineering-এর requirement।&lt;/p&gt;

</description>
      <category>devops</category>
      <category>microservices</category>
      <category>monitoring</category>
      <category>sre</category>
    </item>
    <item>
      <title>Day 28 — CI/CD Pipeline — Commit থেকে Production পর্যন্ত নিরাপদে যান</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Sat, 03 Oct 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-28-cicd-pipeline-commit-theke-production-prynt-niraapde-yaan-3325</link>
      <guid>https://dev.to/mislam-dev/day-28-cicd-pipeline-commit-theke-production-prynt-niraapde-yaan-3325</guid>
      <description>&lt;p&gt;এতদিন তো অনেক কিছুই করলেন কিন্তু এখনো বেশ কিছু জায়গা আছে যেগুলোতে productivity একটু হলেও বাড়াতে পারেন। এবার আপনি development workflow-টাকে একটু optimize করার কথা চিন্তাভাবনা করলেন। এটা মাথায় রেখে আপনি প্রত্যেকটা team-এর workflow analysis করতে বসলেন।&lt;br&gt;
এখানে আপনি অনেকগুলো জিনিস লক্ষ্য করলেন। বিশেষত অনেকগুলো কাজ আছে যেগুলো প্রতিদিন repeatedly করতে হয়। সেগুলো হলো:&lt;/p&gt;

&lt;p&gt;১. manually code test করা লাগে।&lt;br&gt;
২. কোনো feature add হলে সেটা build করে, deploy করতে হয়।&lt;br&gt;
৩. manually test করার কারণে, production-এ যেয়ে অনেক unwanted error দেখা দেয় সেগুলোও solve করা লাগে।&lt;/p&gt;

&lt;p&gt;এছাড়াও এই repeated কাজ করতে করতে team member-রা bore হয়ে যাচ্ছে। তারা কিছু বলছে না কারণ তাদেরকে proper সুযোগ-সুবিধা দেয়া হচ্ছে এর জন্য। না হলে company থেকে চলে যেত।&lt;/p&gt;

&lt;p&gt;উপরে যে repeated task-গুলো রয়েছে, সেগুলো docker এবং k8s introduce করার পর একটু কমে গেছে। আগে অনেক কিছু করা লাগত। এখন docker image build বা k8s deployment use করলেই কাজ শেষ।&lt;/p&gt;

&lt;p&gt;এর পরের বিষয়গুলো তারপরও repeated কাজ। এগুলো automatic করা যায় কি না। তো আপনার মাথায় একটা idea আসল যে, এই কাজগুলো তো same, আপনি যদি একটা shell script লিখে ফেলেন তো কাজ হয়ে যাবে। shell script দিয়ে প্রথমে testing করার জন্য test-গুলো run করবো, then সেটাকে build করার দরকার হলে build করে দেখবো যে কোনো error আছে কি না, and finally সেটাকে deploy করে দেবো।&lt;/p&gt;

&lt;p&gt;এটাকেই বলে CI/CD (Continuous Integration/Continuous Delivery)&lt;/p&gt;


&lt;h2&gt;
  
  
  CI vs CD
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CI (Continuous Integration)&lt;/strong&gt; — প্রতিটা code push-এ automatically test run করা, build করা হয়। মূলত চেকিং এর কাজ টা এই step এ হয়। কোনো problem হলে সেটা সাথে জানাবে এবং সামনের দিকে আগাবে না।&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CD (Continuous Delivery)&lt;/strong&gt; — CI পাস করলে staging-এ automatically deploy হয়ে যাবে।&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CD (Continuous Deployment)&lt;/strong&gt; — Production-এ auto deploy। Human approval নেই।&lt;/p&gt;

&lt;p&gt;বেশিরভাগ team Continuous Delivery করে — staging auto deploy হয় আর production-এ একজন approve করলে তারপর deploy হয়।&lt;/p&gt;


&lt;h2&gt;
  
  
  GitHub Actions: সহজ শুরু
&lt;/h2&gt;

&lt;p&gt;এখন আপনি একটা shell scripting করে আপনার একটা workflow automate করতে পারবেন। shell scripting আপনার একার জন্য একদম ঠিক আছে, কিন্তু আপনার company-তে team অনেক বেশি, অনেক manpower রয়েছে। আপনার style আর তাদের style-টা নাই match হতে পারে। তখন আবার complication বাড়বে। এর জন্য standard কিছু জিনিস দরকার। তবে একটা CI/CD-এর ক্ষেত্রে কোনো fixed standard নেই।&lt;br&gt;
এই standard-তো complication দূর করার জন্য আপনি নানারকমের tool use করতে পারেন। GitHub Actions is one of them।&lt;/p&gt;

&lt;p&gt;নিচে একটা simple CI/CD pipeline লেখা আছে। দেখলে কিছুটা idea পাবেন।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/ci.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node.js&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;20"&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;npm"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run linter&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run lint&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run test:ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub Actions GitHub-এ run হয়। উপরের এই workflow-তে বলা হচ্ছে, যখন main branch-এ কোনো কিছু push করা হবে বা pull request create করা হবে তখন নিচের এই job-গুলো হবে। job-এর name-গুলো দেখলেই বুঝতে পারবেন যে এখানে development environment setup করে, প্রথমে linting, then testing and finally build করেছে। এখানে কোনো step-এ যদি কোনো error হয় তাহলে immediately তা stop হয়ে যাবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker Build + Push
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;build-and-push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Docker image&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker build -t my-app:${{ github.sha }} .&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Push to registry&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;docker tag my-app:${{ github.sha }} ghcr.io/myorg/my-app:${{ github.sha }}&lt;/span&gt;
        &lt;span class="s"&gt;docker push ghcr.io/myorg/my-app:${{ github.sha }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে simply docker image build and push করা হয়েছে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Deploy to Production
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-and-push&lt;/span&gt;
  &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt; &lt;span class="c1"&gt;# manual approval লাগবে&lt;/span&gt;
  &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# OIDC authentication-এর জন্য&lt;/span&gt;
    &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

    &lt;span class="c1"&gt;# 1. AWS/GCP/Azure-এর সাথে নিরাপদ OIDC কানেকশন (কোনো permanent secret ছাড়া)&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Authenticate with Cloud Provider (OIDC)&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::123456789012:role/github-actions-deploy-role&lt;/span&gt;
        &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get K8s Context&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws eks update-kubeconfig --name my-cluster --region us-east-1&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Deploy to K8s&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to K8s&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;kubectl set image deployment/my-app \&lt;/span&gt;
          &lt;span class="s"&gt;my-app=ghcr.io/myorg/my-app:${{ github.sha }}&lt;/span&gt;
        &lt;span class="s"&gt;kubectl rollout status deployment/my-app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;environment: production&lt;/code&gt; দিলে GitHub-এ reviewer approve না করলে deploy হবে না।&lt;/p&gt;




&lt;h2&gt;
  
  
  Branch Strategy: কোথায় কী deploy হবে
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feature/* → CI only (test + lint)
develop   → CI + deploy to staging
main      → CI + deploy to production (manual approve)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Secrets Management
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DATABASE_URL }}&lt;/span&gt;
    &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.API_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;workflow file-এর ভেতরে কোনো configuration related file রাখলে তা leak হওয়ার possibility থাকে। এর জন্য best হচ্ছে GitHub Secrets। এটা securely আপনার environment variable-গুলো maintain করতে help করে।&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;CI/CD মানে শুধু automation না — এটা confidence। Test pass না করলে deploy হবে না। Production-এ কোনো surprises নেই। একবার setup করুন, সারাজীবন সময় বাঁচান।&lt;/p&gt;

&lt;p&gt;বি:দ্র: উপরের যে yaml file গুলা লেখা হয়েছে এইগুলো begginer friendly এবং simple ভাবে লেখা হয়েছে। এই গুলাকে আরও better ভাবে লেখা যেতে পারে।&lt;/p&gt;

&lt;p&gt;আপনার team কোন CI/CD tool ব্যবহার করছে? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>automation</category>
      <category>cicd</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Day 27 — Kubernetes — ভয় পাবেন না, ২০% জানলেই ৮০% কাজ হয়</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Fri, 02 Oct 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-27-kubernetes-bhy-paaben-naa-20-jaanlei-80-kaaj-hy-1l6n</link>
      <guid>https://dev.to/mislam-dev/day-27-kubernetes-bhy-paaben-naa-20-jaanlei-80-kaaj-hy-1l6n</guid>
      <description>&lt;p&gt;এখন আপনার team-এর productivity অনেক বেড়ে গেছে। এখন আপনার application-এর সবকিছুই বলতে গেলে docker এবং docker compose দিয়ে চলে। কিন্তু আপনার application-এর পরিমাণ অনেক বেশি, আলাদা instance রয়েছে, load balancer আছে, database instances আছে। problem হচ্ছে, এখানে আপনি চাইলেই multiple instance run করা যায় তবে এই instance fixed করা থাকে কমানোও যায় না, বাড়ানোও যায় না। শুধুমাত্র আপনাকে manually add করতে হবে। আবার কোনো instance down হয়ে গেলে তাকে restart করার প্রয়োজন হয়। এই সবকিছুই manually করতে হয়। suppose একটা application-এ ৩টা fixed instance আছে। এই ৩টা instance maximum 2k request per second handle করতে পারে। এখন হঠাৎ করে peak time-এ এটা 3k rps-এ চলে গেল। এখন আপনার instance ২টা বাড়াতে হবে। এই আপনি করলেন কিন্তু ১ঘণ্টা পরে load কমে গেল 1k rps-এ। তখন কিন্তু আপনার ২টা instance হলেই enough, বাকি ৩টা instance-এর কিন্তু দরকার নেই। এটা করার জন্য আপনাকে আবার manually code update করে run করা লাগবে।&lt;/p&gt;

&lt;p&gt;এখন এটা যদি প্রতিদিন করা লাগে বিষয়টা কেমন হবে just imagine। এটা তো এখন এর থেকেও বড় কথা হচ্ছে, আপনি বুঝবেন কীভাবে load বেড়ে গেছে? load 100% হয়ে গেলে তো সব instance crash করে যাবে। আরও অনেক problem।&lt;/p&gt;

&lt;p&gt;এখন এটাই যদি automatically করা যেত তাহলে বিষয়টা কেমন হতো?&lt;/p&gt;

&lt;p&gt;আপনার এত tension করা লাগত না। load যখন বেড়ে যাবে তখন automatically instance বেড়ে যাবে (scale up)। load কমে গেলে automatically instance কমতে থাকবে (scale down)। ইচ্ছা মতো container up, down করা যাবে। আরও অনেক problem solve হয়ে যাবে।&lt;/p&gt;

&lt;p&gt;বিষয়টা খুবই interesting, তাই না। এই same কাজটাই করে Kubernetes (K8s)।&lt;/p&gt;




&lt;h2&gt;
  
  
  What is kubernetes?
&lt;/h2&gt;

&lt;p&gt;kubernetes হলো docker compose-এর মতো একটা orchestrator, যার মূল কাজ হচ্ছে container-গুলোকে maintain করা। একে short-এ K8s বলে থাকে। docker compose-এ যেখানে limitation চলে আসে, সেখান থেকেই k8s-এর শুরু। k8s-এর history বলে লাভ নেই। একটু research করলেই পেয়ে যাবেন।&lt;/p&gt;

&lt;p&gt;একটু আগে scale up and scale down-এর কথা বললাম, সেই কাজটা k8s easily করতে পারে, automatic-ভাবে। একে autoscaling বলে। automatically scale হবে। তবে এই autoscalling এর জন্য logic এবং পলিসি আগে থেকে code এ লিখে দিতে হয়। K8s-এর নিজস্ব Service object আছে যা internal load balancing করে, এবং cloud provider-এর সাথে মিলে external traffic handle করা একদম সহজ করে দেয়। এছাড়াও auto healing-এর feature-ও k8s-এ আছে।&lt;/p&gt;

&lt;p&gt;k8s একটা huge জিনিস। এটা মোটামোটি complex, learning curve অনেক long। আর k8s small to medium application-এর জন্য use করা overkill হয়ে যায়।&lt;/p&gt;

&lt;h2&gt;
  
  
  K8s কেন দরকার?
&lt;/h2&gt;

&lt;p&gt;কেন দরকার সেটা কিছুটা আন্দাজ করতে পারছেন। সেই বিষয়ে যাওয়ার আগে নিচের question-গুলো নিয়ে একটু ভাবুন:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Container crash করলে কে restart করবে?&lt;/li&gt;
&lt;li&gt;Traffic বাড়লে container বা instance কে বাড়াবে?&lt;/li&gt;
&lt;li&gt;আবার traffic কমে গেলে instance কে কমাবে?&lt;/li&gt;
&lt;li&gt;১০টা server-এ load কীভাবে distribute হবে?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;উপরে প্রত্যেক problem-এর solution k8s-এ রয়েছে। এছাড়াও k8s zero down time deployment-এর benefit দেয়। এখানে আপনার application down না করেই নতুন version-এ roll করা যায়। server কোনো ভাবেই down হবে না। gracefully old application-গুলো new version-এর application দিয়ে replace করে দেবে with zero down time।&lt;/p&gt;




&lt;h2&gt;
  
  
  মূল Concepts — শুধু এগুলো
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pod&lt;/strong&gt; — K8s সরাসরি container রান করে না, Pod রান করে। এটি ক্লাস্টারের সবচেয়ে ছোট unit, যার ভেতরে এক বা একাধিক container থাকতে পারে (যেমন আপনার main app এবং একটি logging agent)।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt; — আপনার অ্যাপের কতগুলো copy (Pod) চলবে এবং কোন image থেকে চলবে তা define করে। কোনো Pod ক্র্যাশ করলে নতুন Pod তৈরি করা বা Zero-downtime আপডেট দেওয়ার দায়িত্ব মূলত এর।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt; — Pods নশ্বর (mortal), এরা dead হয়ে গেলে নতুন IP দিয়ে আবার নতুন করে রান হয়। Service এদের সামনে একটা Fixed IP ও DNS নাম বসিয়ে দেয়, যেন ডাটাবেস বা অন্যান্য অ্যাপ সহজে এদের খুঁজে পায়।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ingress&lt;/strong&gt; — বাইরের traffic (ইন্টারনেট) ক্লাস্টারের ভেতরে আসার মেইন দরজা বা Router। কোন ডোমেইন বা URL-এ হিট করলে কোন Service-এ ট্রাফিক যাবে, তা Ingress ঠিক করে দেয়।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConfigMap / Secret&lt;/strong&gt; — অ্যাপ্লিকেশনের Environment Variables এবং Configuration কোড থেকে আলাদা রাখার জায়গা। সাধারণ ডাটার জন্য ConfigMap আর পাসওয়ার্ড বা API Key এর মতো সেনসিটিভ ডাটার জন্য Secret ব্যবহৃত হয়।&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Deployment &amp;amp; Service: A Real Example
&lt;/h2&gt;

&lt;p&gt;Kubernetes-এ সবকিছু ডিক্লেয়ার করা হয় YAML ম্যানিফেস্টের মাধ্যমে:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# deployment.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend-app&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt; &lt;span class="c1"&gt;# Zero-downtime rolling update&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend:v1.0.0&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100m"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;128Mi"&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;500m"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;512Mi"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# service.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  HPA (Horizontal Pod Autoscaler): অটো-স্কেলিং 📈
&lt;/h2&gt;

&lt;p&gt;ম্যানুয়ালি ৩টি বা ৫টি Pod নির্দিষ্ট না রেখে, ট্রাফিকের ওপর ভিত্তি করে স্বয়ংক্রিয়ভাবে Pod সংখ্যা বাড়ানো বা কমানোর কাজ করে HPA. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;autoscaling/v2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HorizontalPodAutoscaler&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend-hpa&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-backend-app&lt;/span&gt;
  &lt;span class="na"&gt;minReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;maxReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Resource&lt;/span&gt;
      &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cpu&lt;/span&gt;
        &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Utilization&lt;/span&gt;
          &lt;span class="na"&gt;averageUtilization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt; &lt;span class="c1"&gt;# CPU ব্যবহার ৭০% পার হলে নতুন Pod তৈরি হবে&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  K8s in small application
&lt;/h2&gt;

&lt;p&gt;শুনতে এত জোস লাগলেও, একটা ছোট বা মিডিয়াম সাইজের প্রোজেক্টে, যেখানে ইউজার বেস কম এবং ট্রাফিক প্রেডিক্টেবল, সেখানে K8s সেটআপ করা মানে নিজের পায়ে নিজে কুড়াল মারা। কেন? চলুন একটু ভেঙে বলি:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Overkill Architecture &amp;amp; Complexity:&lt;/strong&gt; Kubernetes এর নিজস্ব একটা বিশাল লার্নিং কার্ভ (Learning curve) আছে। Pods, Deployments, Services, Ingress, ConfigMaps—এসব মেইনটেইন করতেই আপনার জান বের হয়ে যাবে। যে সময়টা আপনি কোড ইমপ্রুভমেন্ট বা বিজনেজ লজিকে দিতে পারতেন, সেটা চলে যাবে ক্লাস্টার কনফিগার করতেই।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure Cost (পকেটের টান):&lt;/strong&gt; K8s চালাতে গেলে মিনিমাম একটা Control Plane (Master Node) আর কয়েকটা Worker Node লাগে। ছোট একটা অ্যাপের যে রিসোর্স লাগবে, তার চেয়ে বেশি রিসোর্স খরচ হয়ে যাবে শুধু Kubernetes ক্লাস্টারটাকে টিকিয়ে রাখতে। ক্লাউড বিল দেখে তখন কপালে হাত পড়বে!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational Overhead:&lt;/strong&gt; এটাকে ম্যানেজ করার জন্য ডেডিকেটেড DevOps ইঞ্জিনিয়ার বা এক্সপার্টাইজ লাগে। ছোট টিমে ডেভলপাররাই যখন DevOps-এর কাজ করে, তখন এই ওভারহেড প্রোডাক্টিভিটি কমিয়ে দেয়।&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;তাহলে উপায় কি?&lt;/p&gt;

&lt;p&gt;আপনার অ্যাপ্লিকেশন যদি ছোট হয়, তাহলে অযথা Kubernetes ব্যবহার করার দরকার নেই। সিম্পল এবং ইফেক্টিভ কিছু অল্টারনেটিভ অলরেডি মার্কেটে আছে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Compose:&lt;/strong&gt; সিঙ্গেল ভার্চুয়াল মেশিনে (VM) মাল্টিপল কন্টেইনার চালানোর জন্য বেস্ট এবং একদম সিম্পল।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Swarm:&lt;/strong&gt; Docker এর নিজের Orchestration tool. K8s এর থেকে অনেক simple আর easy to learn।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed Platforms:&lt;/strong&gt; Render, Railway, বা DigitalOcean App Platform-এর মতো সার্ভিসগুলো ইউজ করতে পারেন। কোনো ইনফ্রাস্ট্রাকচারের চিন্তা ছাড়াই জাস্ট কোড পুশ করলেই লাইভ!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPS (Virtual Private Server):&lt;/strong&gt; একটা সিম্পল Hetzner বা DigitalOcean Droplet-এ Docker দিয়ে সেটআপ করে নিলেই বছরের পর বছর শান্তিতে চালানো যায়।&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;কুবারনেটিস টেকনোলজি হিসেবে অসাধারণ এবং বড় স্কেলের মাইক্রোসার্ভিস আর্কিটেকচারের জন্য এটার কোনো বিকল্প নেই। কিন্তু হাইপ বা ট্রেন্ডের পেছনে ছুটে ছোট অ্যাপে K8s ঢুকিয়ে কমপ্লেক্সিটি বাড়ানোর কোনো মানে হয় না। তবে k8s ব্যবহার করতে হয় তাহলে একেবারে বেসিক দিয়ে শুরু করুন। Deployment, Service, HPA, Ingress — এই চারটা দিয়েই ৮০% production workload handle করা যায়, এই গুলা শিখে শুরু করুন পরে প্রয়োজন হলে শিখে নিবেন।&lt;/p&gt;

&lt;p&gt;আপনি কি K8s ব্যবহার করছেন? সবচেয়ে কঠিন কোন concept মনে হয়েছে? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Day 26 — Docker — 'আমার machine-এ চলে' এই অজুহাত চিরতরে বন্ধ করুন</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Thu, 01 Oct 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-26-docker-aamaar-machine-e-cle-ei-ajuhaat-cirtre-bndh-krun-2i4i</link>
      <guid>https://dev.to/mislam-dev/day-26-docker-aamaar-machine-e-cle-ei-ajuhaat-cirtre-bndh-krun-2i4i</guid>
      <description>&lt;p&gt;আপনার company অনেক বড় হয়ে গেছে। মোটামুটি প্রায় ২০০ জন engineer। হঠাৎ করেই একটা pandemic চলে এল। govt থেকে lockdown দিয়ে দিলো। এখন office-এ যেয়ে কাজ করার সুযোগ নেই। এখন সবাইকেই remotely বাড়ি থেকে কাজ করতে হবে। এখানে আপনার একটা লাভ হলো যে সব engineer-এরই একটা করে computer/laptop আছে। আর ১০-১২ জনের ছিল না, আপনি তাদের জন্য সেটার ব্যবস্থা করে দিলেন।&lt;/p&gt;

&lt;p&gt;এভাবেই office শুরু হলো। কাজ চলতেছে। ১ মাস এই ভাবেই চললো। তারপর আপনি একটা জিনিস realize করলেন কাজের productivity কমে গেছে। আগে যেখানে ১ মাসে ১৫-২০ টা feature আরামসে complete হয়ে যেত, এখন ৪-৫ feature complete করতেই অবস্থা খারাপ হয়ে গেছে। বিষয়টা খুবই concerning। সবগুলো না হোক অন্তত ১২-১৫ টা feature তো complete করতে হবে।&lt;/p&gt;

&lt;p&gt;এই বিষয়টা address করার জন্য আপনি সকল team leader-দের নিয়ে meet করলেন। একটা ২ ঘন্টার long meeting হলো। ভালো খারাপ সব নিয়েই কথা হলো। তবে ভালোর থেকে খারাপ বিষয়গুলোই বেশি ছিল। meeting-এর summary হচ্ছে এই রকম:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"আমার machine-এ কাজ করে": এই simple line নাকি সবার মাঝে common হয়ে গেছে। মূল সমস্যা হলো যখন কেউ কোনো feature develop করে তখন অন্য আরেকজনের computer-এ properly run হয় না, configuration-এর problem। এই problem solve করতেই অবস্থা খারাপ। এই problem solve করার পর, যে develop করেছে তার machine থেকে আবার try করলে আবার same problem। এই ভাবেই দিনের অর্ধেক time চলে যাচ্ছে।&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;এছাড়াও deploy করার সময়ও problem হচ্ছে। সেখানেও critical problem দেখা দিচ্ছে। deploy-এর সময় problem হচ্ছে। properly deploy হচ্ছে না।&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এখানে মূল বিষয় হচ্ছে, engineer যেখানে feature development-এ focus দিবে সেখানে তারা configuration related problem solve করতেই সবচেয়ে বেশি সময় নষ্ট করছে। বিষয়টা আসলেই গুরুতর।&lt;/p&gt;

&lt;p&gt;আপনার একটা জিনিস মাথায় আসল, আগে office থাকতে তো এই রকম কোনো problem হয়নি তাহলে এখন এত problem হচ্ছে remotely কাজ করার জন্য? না, remotely কাজ করলে তো আর তাদের skill কমে যাবে না। বিষয়টা হচ্ছে আগে যখন সবাই office-এ কাজ করত তখন সবাই same configuration-এর machine use করত। সবার machine same ছিল। আর সবাই একসাথে কাজ করার কারণে কোনো সমস্যা হলে instant solve হয়ে যেত।&lt;/p&gt;

&lt;p&gt;এটা কীভাবে solve করা যায়। সবাইকে তো আর same machine দিয়ে দেয়া যাবে না। আর সবার কাছে তো same type computer নেই। কেউ linux, কেউ windows আবার macOS use করে। এখন চাইলেই এটা করা যাবে না। এর থেকে better solution লাগবে।&lt;/p&gt;

&lt;p&gt;solution কি আছে??&lt;/p&gt;

&lt;p&gt;হ্যাঁ, অবশ্যই আছে। His name is Docker।&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;docker হলো একটা tool বা software, এটা use করে আপনার problem easily solve করা যায়। docker containerization নামে একটা feature আছে যেটা আপনার application-কে একটা isolated environment-এ run করবে। এই environment-টায় একটা dedicated operating system থাকে। এই operating system-এ outsider-এর কোনো effect থাকে না সেটা linux হোক, বা windows হোক, বা macOS হোক।&lt;/p&gt;

&lt;p&gt;এখানে অনেকটা ship-এর কথা চিন্তা করতে পারেন। জাহাজে কিন্তু অনেক container থাকে। সেখানে কিন্তু একটা container অন্য একটা container-কে affect করে না। যে যার মতো। ভেতরে যা আছে সবকিছুই isolated। আর ship কিন্তু অনেকগুলো container একসাথে carry করতে পারে।&lt;/p&gt;

&lt;p&gt;এখানে docker container হলো ship-এর container আর ship-টা হচ্ছে host machine। তবে আপনার laptop, বা computer বা macOS যেটাই হোক না কেন, সেটাই basically host machine।&lt;/p&gt;

&lt;p&gt;docker-এর সবচেয়ে বড় সুবিধা হচ্ছে, আপনার machine-এ যা চলছে যেভাবে চলছে, ঠিক সেভাবে আপনার colleague-এর machine-এ, আবার production server-এ same ভাবেই run করবে। আর কেউ কিছু change করলেও same configuration-এর কারণে same result-ই পাবে। "আমার machine-এ কাজ করে" এটা থেকে মুক্তি পেয়ে যাবেন।&lt;/p&gt;

&lt;p&gt;আপনি যদি docker-এ নতুন হন তাহলে একটু confusion হতে পারে। আমারও হয়েছিল। আস্তে আস্তে সবকিছু clear হয়ে যাবে।&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not Virtual Machine?
&lt;/h2&gt;

&lt;p&gt;আপনি যদি কখনো virtual machine use করে থাকেন তাহলে আপনার মনে এই question-টা আসতেই পারে। VM machine করলেই তো হয়। এত complicated জিনিসের বা কী দরকার। হ্যাঁ, অবশ্যই দরকার।&lt;/p&gt;

&lt;p&gt;বিষয়টাতে যাওয়ার আগে docker কীভাবে কাজ করে সেটা জানার প্রয়োজন। Docker কোনো আলাদা Operating System run করে না। এটি Host machine-এর kernel share করে এবং শুধুমাত্র অ্যাপ্লিকেশনের জন্য প্রয়োজনীয় library ও dependency গুলো রান করে। আর host machine এর resource by default ভাবেই use হবে। এই architecture-এর কারণেই একটা docker container-এর size খুবই lightweight হয়। একটা typical nodejs এর docker image এর size 50-100mb এর মধ্যে হয়। তবে container রান করলে সেখানে মোটামুটি ৫০০-৭০০mb ram use হতে পারে।&lt;/p&gt;

&lt;p&gt;vm-এ সবকিছুই তার own operating system + own kernel + more isolated environment। এই সমস্ত কারণে vm-এর size খুবই বেশি হয়। অনেক ক্ষেত্রে 5-10gb হয়ে যায়। আর startup time অনেক বেশি।&lt;/p&gt;

&lt;p&gt;এখন চিন্তা করেন, সবাইকে যদি এই 5-10gb-এর vm-কে transfer করা যায়, setup করা ঝামেলা। আর suppose কেউ কোনো feature add করলো তখন তো পুরো vm-টাই transfer করা লাগবে। কী একটা pain!&lt;/p&gt;

&lt;p&gt;এখানে docker help করে, আপনি চাইলে আপনার code দিয়ে আপনার নিজের machine-এই docker container build করতে পারেন। আপনার 700-800mb container transfer করা লাগবে না।&lt;/p&gt;

&lt;p&gt;এই সমস্ত কারণেই মূলত docker-টা use করাই সবচেয়ে ভালো। এছাড়াও আরও অনেক সুবিধা আছে। যেমন ধরুন deployment একদম পানির মতো easy করে দিবে। CI/CD নিয়ে আলোচনা হবে তখন deployment নিয়ে কথা হবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Dockerfile: Recipe লিখুন
&lt;/h2&gt;

&lt;p&gt;আপনারা যারা জীবনে একবার হলেও, computer-এ windows বা linux setup করেছেন তখন দেখবেন, আপনাকে অনেক কিছু set করে দিতে হয়। windows-এর কোন version use করবেন বা linux-এর মধ্যে কোন linux, ubuntu নাকি mint নাকি অন্য কিছু। এবং এই সবকিছু ঠিক করার পরে কিন্তু মোটামুটি অনেক time লাগে setup complete হতে।&lt;/p&gt;

&lt;p&gt;কখনো ভেবে দেখেছেন এই সময়টাতে কী হয়? এই সময়েই মূলত OS-এর জন্য file-গুলো আসে সেগুলো ready করা হয় এবং আপনার system-এর drive-এ push করা হয়। নানারকম system preference আছে সেগুলো set করা হয়। যখন সবকিছু ঠিক হয়ে যায় তারপরে যেয়ে আপনি computer use করতে পারেন।&lt;/p&gt;

&lt;p&gt;একটু আগে আমি বললাম যে docker operating system run করে application run করে। সে তো আর জানে না যে আমার কোন operating system use করতে হবে আর use করার পর application-টাকে কীভাবে setup করে run করতে হবে। তাকে তো বলে দিতে হবে। না হলে তো কিছুই বুঝবে না। For example, আপনার nodejs application run করার জন্য আপনার system-এ nodejs install থাকতে হবে। তা নাহলে তো সেই application run হবে না।&lt;/p&gt;

&lt;p&gt;এটার জন্য একটা recipe বা configuration লিখতে হয়, যাকে বলে dockerfile। নিচে একটা dockerfile-এর example দেখতে পারবেন।&lt;br&gt;
ভয় পাওয়ার দরকার নেই আস্তে আস্তে শিখে যাবেন। খুব কঠিন কিছু না।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20-alpine&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "dist/main.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে একটা nodejs application run করার জন্য লেখা হয়েছে। Node-20 এর alpine version-টা use করা হয়েছে এবং প্রয়োজনীয় সকল dependencies-গুলো setup করা হয়েছে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer Caching: Build Fast করুন
&lt;/h2&gt;

&lt;p&gt;উপরের dockerfile দেখে একটা question arise হতে পারে। যে এত line লেখার কী আছে। 3-4 line-এই তো শেষ করা যেতে পারে।&lt;br&gt;
এখানেই বিষয়টা সে docker-এর build process। dockerfile build হওয়ার time-এ line by line data cached করে রাখে। যেই line থেকে আবার নতুন করে build হবে। For example,&lt;br&gt;
আপনি যদি package.json file কোনো change না করে থাকেন তাহলে সেটা &lt;code&gt;COPY . .&lt;/code&gt; থেকে নতুন build শুরু হবে। তার আগে যেগুলো build হয়েছে সেগুলো cached data থেকে use করবে। আর যদি package.json file-এ change করে থাকেন তাহলে ঐ line থেকে আবার নতুন করে build শুরু হবে।&lt;br&gt;
এই জন্যই মূলত dockerfile multiple line-এ লেখা হয়। এতে container-এর size কমে।&lt;/p&gt;

&lt;p&gt;নিচের example দেখলে আরও ভালো বুঝতে পারবেন।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# ✅ dependencies আগে — কম পাল্টায়&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci

&lt;span class="c"&gt;# ✅ source code পরে — বেশি পাল্টায়&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Docker Image
&lt;/h2&gt;

&lt;p&gt;আপনি যখন কোনো OS setup করেন তখন আপনার কাছে একটা .img file থাকে। এই file-টা আপনার system computer-এ setup করার পরেই কিন্তু windows run হয়।&lt;br&gt;
এখানে বোঝার বিষয় হচ্ছে, এখানে এই .img file-টা কিন্তু একা একা চলতে পারবে না। বা আপনার ঐ .img-টা বাদেও শুধু hardware দিয়ে কাজ হবে না। মূলত operating system-এর সব files (kernel, system files, file systems etc.) এই .img file-এর মধ্যে থাকে, অনেকটা zip file-এর মতো করে একসাথে করে রাখা হয়।&lt;/p&gt;

&lt;p&gt;docker-এর জন্য, only application run করার জন্য needed files-গুলো একসাথে করে একটা file create করা হয়। এইগুলো কে docker image বলে। এই image-গুলোকে একটা container-এর মধ্যে run হয়। আর container কীভাবে কাজ করে উপরে মোটামুটি বলেছি বুঝে গেছেন।&lt;/p&gt;

&lt;p&gt;Dockerfile থেকেই এই image-গুলো create করতে হয়। তারপর docker-এর মাধ্যমে এগুলো run করতে হয়।&lt;/p&gt;
&lt;h2&gt;
  
  
  Multi-Stage Build: প্রোডাকশন ইমেজ সাইজ ৮০% কমান ⚡
&lt;/h2&gt;

&lt;p&gt;একটি সাধারণ TypeScript বা modern Node.js app-কে বিল্ড করার জন্য TypeScript কম্পাইলার &lt;code&gt;tsc&lt;/code&gt;, &lt;code&gt;linter&lt;/code&gt; এবং অনেক &lt;code&gt;devDependencies&lt;/code&gt; দরকার হয়। কিন্তু প্রোডাকশনে এই app এর build run করলেই হয়ে যায়।&lt;/p&gt;

&lt;p&gt;এগুলোকে image-এ রেখে দিলে dokcer image এর size 700-800 mb হয়ে যায়। ক্ষেত্র বিশেষ আরও বেশিও হতে পারে। এই সমস্যার সেরা সমাধান হলো &lt;strong&gt;Multi-Stage Build&lt;/strong&gt;। এখানে শুধু একটা stage থেকে আরেকটা stage-এ প্রয়োজনীয় ফাইলগুলা transfer হবে।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# --- Stage 1: Build Stage ---&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:20-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build


&lt;span class="c"&gt;# --- Stage 2: Production Runtime Stage ---&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:20-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;runner&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;

&lt;span class="c"&gt;# শুধু প্রোডাকশন ডিপেন্ডেন্সি ইনস্টল&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev

&lt;span class="c"&gt;# স্টেজ ১ থেকে শুধু বিল্ড হওয়া dist ফোল্ডার কপি&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/dist ./dist&lt;/span&gt;

&lt;span class="c"&gt;# Security: Root হিসেবে রান না করে non-root user ব্যবহার&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; node&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "dist/main.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এর সবচেয়ে বড় সুবিধা হচ্ছে docker image-এর size ৭০-৮০% কমে যায়। এছাড়াও production-এর জন্য প্রয়োজনীয় ফাইলগুলোই image-এর ভেতরে থাকে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker Compose: Multi-Service Local Dev
&lt;/h2&gt;

&lt;p&gt;একটা জিনিস, আপনার application-এ কিন্তু অনেক configuration করতে হয়। এগুলো application-এর outside থেকে provide করতে হবে। না হলে একটা security risk তৈরি হতে পারে। এখন আপনি চাইলেই আপনার docker container প্রতিবার configurations type করে run করতে পারেন। কিন্তু যদি নতুন কোনো কিছু add করা লাগে বা delete করা লাগে তখন কী করবেন? তখন কিন্তু বিষয়টা pain হয়ে যাবে। এছাড়া আমি একটু বললাম যে, docker system resource use করে, সেখানেও তো limit করা লাগবে। এগুলো তো arbitrary ভাবে করা যাবে না। একটা proper way লাগবে।&lt;/p&gt;

&lt;p&gt;এই problem-টাকে address করার জন্য, docker introduce করে, একটা orchestrator, যেটা হলো docker compose। একটা band-এ orchestrator কী করেন সেটা তো জানেন। তিনি instruction দেন কখন কোন instrument-টা বাজাতে হবে, কতক্ষণ বাজবে এবং কখন বন্ধ হবে etc. মানে তিনিই সবকিছু control করে থাকেন। docker compose-ও same কাজটাই করে থাকে।&lt;/p&gt;

&lt;p&gt;docker compose মূলত image file run করে। আর মজার ব্যাপার হচ্ছে এই compose file দিয়েই docker image build করা যায়। আর সেই image-গুলো compose file দিয়েই run করা যায়। এছাড়াও existing image-ও run করা যায়।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# application container&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt; &lt;span class="c1"&gt;# builidng with existing Dockerfile file&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt; &lt;span class="c1"&gt;# mapping port 3000 of host to container&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# environment variables&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql://postgres:password@db:5432/mydb&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# dependencies&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# container for database&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16-alpine&lt;/span&gt; &lt;span class="c1"&gt;# existing external postgres image&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# environment variables&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydb&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pgdata:/var/lib/postgresql/data&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:7-alpine&lt;/span&gt; &lt;span class="c1"&gt;# external redis image&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pgdata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# volume data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে PostgreSQL database and redis-এর জন্য external image use করা হয়েছে।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এই একটা command-এ সবগুলো container একসাথে run হবে। কোনো কিছু করা লাগবে না। এক বারে সবকিছু ready।&lt;/p&gt;




&lt;h2&gt;
  
  
  .dockerignore: অপ্রয়োজনীয় বাদ দিন
&lt;/h2&gt;

&lt;p&gt;এই পর্যন্ত যখন এসেছেন তাহলে git সম্পর্কে অবশ্যই জানেন। use-ও করতে পারেন। একটা জিনিস খেয়াল করবেন, আপনি কিন্তু github-এ node_modules, configurations, .env, build files এগুলো push করেন না। কেন করেন না? কারণ এগুলো আপনি চাইলেই externally install করতে পারবেন। docker-এর ক্ষেত্রেও একই rules প্রযোজ্য।&lt;/p&gt;

&lt;p&gt;git-এর জন্য .gitignore use হয়, docker-এর জন্য .dockerignore file use হয়।&lt;/p&gt;

&lt;p&gt;অনেকে মনে করেন এটি শুধু ইমেজ সাইজ ছোট রাখার জন্য ব্যবহার করা হয়। কিন্তু এর চেয়েও বড় একটি কারণ রয়েছে।&lt;br&gt;
আপনার লোকাল ল্যাপটপ যদি macOS বা Windows হয়, আপনার লোকাল &lt;code&gt;node_modules&lt;/code&gt;-এ থাকা লাইব্রেরিগুলো (যেমন &lt;code&gt;bcrypt&lt;/code&gt;, &lt;code&gt;sharp&lt;/code&gt;, &lt;code&gt;prisma&lt;/code&gt;) আপনার নিজস্ব OS-এর আর্কিটেকচারে কম্পাইল করা থাকে। &lt;code&gt;.dockerignore&lt;/code&gt;-এ &lt;code&gt;node_modules&lt;/code&gt; না রাখলে &lt;code&gt;COPY . .&lt;/code&gt; কমান্ডটি সেই ফাইলগুলো ডকারের Linux কন্টেইনারে কপি করে দেবে—যার ফলে কন্টেইনারে &lt;strong&gt;&lt;code&gt;invalid ELF header&lt;/code&gt;&lt;/strong&gt; বা আর্কিটেকচার মিসম্যাচ এরর দিয়ে অ্যাপ ক্র্যাশ করবে!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
.git
.env
*.log
dist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;উপরের যে list-এ যেগুলো আছে এগুলোর খুব বেশি দরকার নেই। এখানে .env file-টাও skip করা হয়েছে, security risk এর জন্য।&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;Docker simply আপনার development workflow smooth and easy করে দিবে। অনেক problem-এর solution করবে যেগুলো হয়তো আপনি চিন্তাও করতে পারবেন না। একটা distributed system, distributed remote team-এর জন্য docker must।&lt;/p&gt;

&lt;p&gt;আপনার project-এ Docker ব্যবহার করছেন? কোন সমস্যায় পড়েছেন? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Day 25 — Circuit Breaker Pattern — একটা service-এর ব্যর্থতায় পুরো system যেন না পড়ে</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Wed, 30 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-25-circuit-breaker-pattern-ekttaa-service-er-byrthtaay-puro-system-yen-naa-pdde-4mkg</link>
      <guid>https://dev.to/mislam-dev/day-25-circuit-breaker-pattern-ekttaa-service-er-byrthtaay-puro-system-yen-naa-pdde-4mkg</guid>
      <description>&lt;p&gt;আপনার application, আপনার business সবকিছুই আরামসে চলছে। এখন আপনি লাখপতি থেকে কোটিপতি হয়ে গেছেন। এতদিনে আপনি একটা জিনিস বুঝে গেছেন। server not found error বা server timeout error থেকে server is under maintenance error টা তুলনামূলক ভাবে ভালো।&lt;/p&gt;

&lt;p&gt;এখন আপনার application-এ তেমন critical error নেই। যা ছিল সব solve হয়ে গেছে।&lt;/p&gt;

&lt;p&gt;কিন্তু মাঝে মাঝে কয়েকটা incident হচ্ছে যেখানে আপনার server crash করছে নানা কারণে। এই জিনিসটা এখন solve করা দরকার। এখন এখানে auto recover করার system-টা on করতে হবে। কিন্তু problem হচ্ছে, system জানবে কীভাবে যে system recover করেছে। আর এই recover করার সময়েই তো user-দেরকে stop করতে হবে। তারা যেন server-এ access করতে না পারে। access করলে তো আবার problem হয়ে যেতে পারে। recover fail করতে পারে। তখন আবার problem।&lt;/p&gt;

&lt;p&gt;এর একটা ব্যবস্থা করা দরকার। বিষয়টা এমন না যে করতেই হবে। কারণ এই case-গুলো মাঝে মাঝে rarely হয়ে থাকে। তবে এতে user-এর experience নষ্ট হবে।&lt;/p&gt;

&lt;p&gt;এই problem-এর solution already বিদ্যমান, Circuit Breaker।&lt;/p&gt;




&lt;h2&gt;
  
  
  Circuit Breaker কীভাবে কাজ করে?
&lt;/h2&gt;

&lt;p&gt;আমরা সবাই মোটামুটি electric circuit breaker সম্পর্কে জানি। জানার কথা। অনেক জায়গায় এটাকে main switch-ও বলে। এই electric circuit breaker-এর কাজ হচ্ছে, যখন প্রয়োজনের তুলনায় load বেশি হবে তখন connection-টাই বন্ধ করে দেবে। এতে করে কোনো unwanted situation create-ই হবে না। for example, বৃষ্টির সময় বজ্রপাত হলে এইসব circuit breaker-গুলো connection বন্ধ করে দেয়। এতে electric device-গুলো protect হয়ে যায়।&lt;/p&gt;

&lt;p&gt;electrical circuit breaker-এর মতো করেই software circuit breaker কাজ করে। যখন system-এ কোনো problem হয় তখন সেটা protect করে। application-কে recover হওয়ার সময় দেয়।&lt;/p&gt;

&lt;p&gt;এখানে তিনটা state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Closed (Normal)&lt;/strong&gt; — এই state-এর মানে হচ্ছে circuit close আছে, request normal way-তে যাবে। কোনো request fail হলে request-গুলো count হবে। এই failure count একটা threshold cross করলে circuit open state-এ চলে যাবে।&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open (Tripped)&lt;/strong&gt; — এই state-এর মানে হচ্ছে circuit open হয়ে গেছে। আর কোনো request-ই process হবে না। direct fallback return হবে। এই state-এ আরেকটা কাজ করা হয়ে থাকে, এখানে একটা সময় পরে যেয়ে circuit half-open state-এ চলে আসবে।&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Half-Open (Testing)&lt;/strong&gt; — এই state সবচেয়ে বেশি important। এই state-এ মূলত check হয় যে system recover করেছে কি না। যদি recover হয়ে থাকে তাহলে circuit-এ আবার closed state-এ চলে যাবে। আর যদি fail হয় তাহলে open state-এ চলে যাবে এবং আরেকটু বেশি সময় wait করবে। এই waiting time-টা generally exponential হয়ে থাকে।&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Basic Implementation
&lt;/h2&gt;

&lt;p&gt;এখানে একটা simple circuit breaker implement করা হয়েছে। এটা simple একটা। আপনার requirement অনুযায়ী আপনি আপনার মতো করে বানিয়ে নিতে পারেন। কীভাবে করবেন সেটা আপনার requirement এবং decision-এর উপর depend করছে।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// nestjs-opossum বা custom implementation&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;failureCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;failureThreshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;recoveryTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 30s&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;lastFailureTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;isTestingRecovery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Single-trial guard for HALF_OPEN&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 1. OPEN to HALF_OPEN Transition Check&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastFailureTime&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoveryTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Circuit is OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. HALF_OPEN State: Allow only ONE trial request&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTestingRecovery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Another probe request is already in-flight; fallback for others&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Circuit is recovering (HALF_OPEN)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTestingRecovery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTestingRecovery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Reset counter on success!&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTestingRecovery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastFailureTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTestingRecovery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureThreshold&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে আপনাকে প্যারা নেয়ার দরকার নেই। বানাতে সময় লেগে যেতে পারে। bug থাকার possibility তো থাকেই। এর জন্য existing অনেক library আছে যেখানে অনেক feature already exist করে। for example,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;opossum&lt;/strong&gt; in nodejs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;resilience4j&lt;/strong&gt; in java&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sony/gobreaker&lt;/strong&gt; in golang&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;failsafe-rs&lt;/strong&gt; in rust&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pybreaker&lt;/strong&gt; in python&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Fallback: Graceful Degradation
&lt;/h2&gt;

&lt;p&gt;Circuit open হলে কী return করব?&lt;/p&gt;

&lt;p&gt;এই question-টা circuit breaker-এর implementation-ই change করে দিবে। এখানে আপনাকেই decision নিতে হবে যে আসলে আপনি কী return করবেন। এখানে fallback strategy-তে কিছু option আছে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return static/cached/default/partial data&lt;/li&gt;
&lt;li&gt;Return exception with error message&lt;/li&gt;
&lt;li&gt;Inform user about the issue&lt;/li&gt;
&lt;li&gt;Show skeleton/loading state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এখন আপনি কোনটা use করবেন সেটা আপনার application-এর উপর depend করছে। for example,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;একটা blog site-এ আপনি চাইলেই cached data fallback হিসেবে দিতে পারেন।&lt;/li&gt;
&lt;li&gt;ecommerce-এর ক্ষেত্রে cached data use করা যেতে পারে। কারণ product-এর details তো আর খুব একটা change হয় না। তবে এখানে আপনার requirement-এর উপর depend করবে যে আপনি কী করবেন।&lt;/li&gt;
&lt;li&gt;banking-এর ক্ষেত্রে আপনি এখন কিন্তু cached data fallback হিসেবে দিতে পারেন না। কারণ এখানে current data-টা খুবই important। এখানে হয় error return করে user-কে inform করাটা better হবে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এই রকম আরও situation-এ পড়তে পারেন। এইসব জিনিসটা আপনার requirement এবং application-এর উপর depend করবে। এখানে কোনো boundary নেই। আপনার যেটা দরকার সেটাই করবেন। NO worries।&lt;/p&gt;

&lt;p&gt;এখানে just simple একটা fallback দিয়ে code generate করা হয়েছে।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;productService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="c1"&gt;// fallback&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;আপনি যখন partial বা cached data fallback হিসেবে use করছেন তখন কিন্তু user কিছু একটা দেখতে পাচ্ছে। application-টা full blank হয়ে যাবে না। এই জিনিসটাকে বলে &lt;strong&gt;Graceful Degradation&lt;/strong&gt;।&lt;/p&gt;




&lt;h2&gt;
  
  
  Retry Pattern: বুদ্ধিমানের মতো retry
&lt;/h2&gt;

&lt;p&gt;উপরে একটা জিনিসের হালকা কথা বলেছিলাম যে, একটা সময় পর circuit breaker check করবে যে system ঠিক আছে কি না। fail করলে একটা সময় পরে আবার retry করতে হবে। এই retry করার time-টা এমনভাবে use করতে হবে যেন আপনার system recover হওয়ার আগেই fail করে না যায়। এই retry-এর time-টা most of the time exponential time use করা হয়ে থাকে। এতে করে server enough time পাবে recover করার জন্য। নিচের example-টা থেকে বিষয়টা বুঝতে পারবেন।&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exponential Backoff&lt;/strong&gt; — প্রতিবার wait বাড়াও:&lt;br&gt;
1st retry: 1 second পর&lt;br&gt;
2nd retry: 2 seconds পর&lt;br&gt;
3rd retry: 4 seconds পর&lt;br&gt;
4th retry: 8 seconds পর&lt;/p&gt;

&lt;p&gt;অনেক ক্ষেত্রে exponential backoff use করার পরও server recover হয় না। তখন একটা maximum time set করে দিতে হয়, যাতে করে server-এর ওপর বেশি pressure না পড়ে। আবার অনেক সময় অনেকগুলো client একসাথে request send করে তখন আরেকটা issue হতে পারে। সেক্ষেত্রে jitter technique use করা যেতে পারে।&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;Microservice আর distributed system-এ failure inevitable। Circuit Breaker, Retry — এই pattern গুলো failure-কে gracefully handle করে। একটা dependent service-এর failure পুরো system ফেলে দিতে পারবে না।&lt;/p&gt;

&lt;p&gt;আপনার system-এ কোন resilience pattern ব্যবহার করছেন? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Day 24 — CQRS ও Event Sourcing</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Tue, 29 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-24-cqrs-o-event-sourcing-168m</link>
      <guid>https://dev.to/mislam-dev/day-24-cqrs-o-event-sourcing-168m</guid>
      <description>&lt;p&gt;আপনার application দিব্যি চলেছে, traffic বাড়ছে। এখন Perfectly সবকিছু চলছে। Business-ও grow করছে, profit-ও দিন দিন বাড়ছে। ভালোই। এভাবেই ২-৩ মাস ভালোই চললো। কিন্তু সমস্যা হলো database load নিয়ে। Database slow হয়ে গেলো। User-রা তাদের important information-গুলো পাচ্ছে না।&lt;/p&gt;

&lt;p&gt;আগের মতোই, same way-তে application debugging শুরু করলেন। এখন কিন্তু আপনি একা না। তাই কয়েক ঘণ্টার ভেতরেই সব issue-গুলো পেয়ে গেলেন। সমস্যাগুলো ঠিক এরকম:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Feed application-এ post read-এর থেকে write বেশি হচ্ছে। Caching দিয়েও কাজ হচ্ছে না। কারণ frequently write হচ্ছে। আর cache regularly invalidate হচ্ছে। Read বেশি হওয়ার কারণে database-এর limit শেষ হয়ে যাচ্ছে। অনেক read হওয়ার কারণে অনেক user write করতে পারছে না।&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache service এখানে অনেকটা useless হয়ে যাচ্ছে কারণ frequently cache update করতে হচ্ছে।&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এখন problem তো পেয়ে গেছেন। আর আপনি ভালো করেই জানেন problem properly খুঁজে বের করা মানেই problem অর্ধেক solve হয়ে গেছে। এখন আপনার মাথায় একটা idea আসলো, read আর write-এর জন্য আলাদা database use করলে কেমন হয়। কিন্তু এতোদিনে বুঝে গেছেন, একটা simple জিনিসকে distribute করলে সেখানে limitless problem হাজির হয়। Distribute system is nightmare.&lt;/p&gt;

&lt;p&gt;আপনার এই idea-টা আপনি আপনার team member-দের কাছে share করলেন, brain storming শুরু হলো। অনেকগুলো question এবং possible complexity-গুলো হাজির হলো। যেমন:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;২টা database maintain কিভাবে করবো, manpower লাগবে, budget লাগবে।&lt;/li&gt;
&lt;li&gt;Write এবং read database-এর জন্য আলাদা আলাদা model, access modifier, response change হওয়ার possibility থাকতে পারে।&lt;/li&gt;
&lt;li&gt;Write-এর জন্য যে schema use করবো, তার সাথে read-এর জন্য আলাদা schema use করলে communication কিভাবে করবো।&lt;/li&gt;
&lt;li&gt;Data replicate কিভাবে করবো, read এবং write database-এর ভেতরে replication-টা কিভাবে হবে।&lt;/li&gt;
&lt;li&gt;কোনো একটা database fail হলে কি হবে। Backup কিভাবে নিবো। Failover-টা কিভাবে হবে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এখন এই প্রত্যেকটা problem solve করার জন্য, আপনি যদি নিজে solution বের করতে চান, তাহলে সময় লাগবে, manpower লাগবে।&lt;br&gt;
কিন্তু কথা হচ্ছে, আপনার এতো চিন্তা করা লাগবে না, এই problem-গুলো address করার জন্য একটা architecture already বিদ্যমান আছে।&lt;br&gt;
CQRS (Command Query Responsibility Segregation) is the solution.&lt;/p&gt;


&lt;h2&gt;
  
  
  CQRS: Command Query Responsibility Segregation
&lt;/h2&gt;

&lt;p&gt;CQRS-এর full form হচ্ছে Command Query Responsibility Segregation। নামটা শুনে কেমন একটা মনে হচ্ছে যে, কোনো responsibility আলাদা করা লাগবে। এখানে command-এর মানে write operations এবং query-এর মানে হচ্ছে read operation। CQRS pattern-এ read আর write operation-এর যে responsibility আছে সেটা segregate বা আলাদা করা।&lt;/p&gt;

&lt;p&gt;নিচের code-গুলো দেখেন। দেখলে idea-টা পাবেন।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// সব কাজ একই model&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CQRS-এ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Write side — Command&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;commandBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UpdateUserCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Read side — Query&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;queryBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GetUserQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  কেন আলাদা করব?
&lt;/h2&gt;

&lt;p&gt;এখন আপনার arise হওয়া question-গুলোর solution CQRS-এ already বিদ্যমান।&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;আপনি কিন্তু এখন আর একা নন। আপনার team আছে। Manpower আছে। এটাকে easily handle করা যাবে। আর profit-ও তো হচ্ছে। এর জন্য নতুন ১-২ জন hire করলে খুব বেশি problem হবে না। বা আপনার existing team member-দের এখানে assign করলেই হয়ে যাবে।&lt;/li&gt;
&lt;li&gt;এটা CQRS model-এর issue না। মূলত এটা আপনার development এবং UI-কে optimize করতে help করবে। কারণ write-এর operation থাকবে business এবং database perspective-এ আর read operation related কাজগুলো হবে UI optimization করার জন্য। সেখানে response model আলাদা রাখলে কোনো problem হবে না।&lt;/li&gt;
&lt;li&gt;এই Architecture কাজ করবে asynchronous model-এ। প্রথমে সবকিছুই write database-এ write হবে, then, eventually সেই data read DB-তে asynchronously replicate হবে।&lt;/li&gt;
&lt;li&gt;২টা database-এর মধ্যে data synchronization-এর জন্য event use করা হয়। এটাকে আপনি event driven architecture-ও বলতে পারেন। আর event driven architecture সম্পর্কে তো অনেক আগে থেকেই জানেন।&lt;/li&gt;
&lt;li&gt;Write DB-টাই মূলত database-এর source of truth। Read DB, write থেকেই replication হয়। কোনো কারণে read DB fail করলে, write DB থেকে replicate করে নিলেই হয়ে যাবে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এগুলো সবই CQRS-এর part।&lt;/p&gt;

&lt;p&gt;Read write operation আলাদা কেন করবেন সেটা তো already বুঝে গেছেন।&lt;/p&gt;




&lt;h2&gt;
  
  
  Event Sourcing: History-র পুরো বই
&lt;/h2&gt;

&lt;p&gt;Event সম্পর্কে মোটামুটি idea হয়ে যাওয়ার কথা। এখন বলবেন event আর event sourcing তো একই জিনিস। না। Event sourcing বোঝার আগে একটা গল্প বলি।&lt;/p&gt;

&lt;p&gt;মনে করুন, আপনার application-এর জন্য একটা bank account খুললেন। খোলার পরে ৫০,০০০ টাকা deposit করলেন। এরপর ২০,০০০ টাকা withdraw করলেন। ৫,০০০ টাকা transfer করলেন। তারপরে আবার ১০,০০০ টাকা deposit করলেন।&lt;/p&gt;

&lt;p&gt;এখন আপনার account-এ কত টাকা আছে? কিন্তু এখানে সমস্যা হচ্ছে আপনার কাছে এমন কোনো access নেই যার মাধ্যমে আপনি জানতে পারবেন যে আপনার current balance কত। এখানে আপনি একটু বুদ্ধি খাটিয়ে বের করে ফেলতে পারেন, আপনি যা করেছেন সেগুলো replay বা calculate করে। তাহলে final balance কত হবে: ৫০,০০০ - ২০,০০০ - ৫,০০০ + ১০,০০০ = ৩৫,০০০।&lt;/p&gt;

&lt;p&gt;Event sourcing জিনিসটা অনেকটা এরকম। কোনো single value store না করে event-গুলো properly store করে, সেগুলো process করে current state কে বের করা হয়। এই যে কোনো single state use না করে event-গুলো store করে সেগুলো process করাই হচ্ছে event sourcing।&lt;/p&gt;

&lt;p&gt;একটা example দিলে বুঝতে পারবেন। সাধারণত আমরা current state-কেই database-এ store করি এবং সেটাই প্রয়োজনে mutate করে use করি। For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;user:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;balance:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে বোঝাচ্ছে user-এর balance ৫০০০। এখন deposit বা withdraw করলে current state update হয়ে যাবে। Transfer করলেও এই same state mutate হবে।&lt;/p&gt;

&lt;p&gt;কিন্তু event sourcing-এর ক্ষেত্রে কোনো fixed state থাকে না। Multiple event-গুলো store রাখা হয়। For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AccountOpened { balance: 10000 }
MoneyWithdrawn { amount: 2000 }
MoneyDeposited { amount: 500 }
MoneyWithdrawn { amount: 3500 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে আগের মতো কোনো fixed state কিন্তু নেই। এখানে সবগুলোই event এবং সেগুলো properly sequence way-তে store করা। এখন আমার balance জানতে হলে এগুলো replay করতে হবে। Replay করার পরে balance হবে: ১০,০০০ - ২,০০০ + ৫০০ - ৩,৫০০ = ৫,০০০। এই জিনিসটাই কিছু আগে কিন্তু একবার করেছেন।&lt;/p&gt;




&lt;h2&gt;
  
  
  Event Sourcing-এর জাদু
&lt;/h2&gt;

&lt;p&gt;Event sourcing জিনিসটার concept-টা একদম simple। কিন্তু implementation একটু complex। কিন্তু যেখানে প্রতিটি event বা operation আপনার জন্য important, সেখানে শুধুমাত্র এই event sourcing-ই use করা হয়। For example:&lt;/p&gt;

&lt;p&gt;Banking sector-এ একজন user-এর প্রত্যেকটা event store করে রাখা প্রয়োজন, কারণ যেকোনো সময়ে audit বা legal requirement-এর জন্য আপনাকে প্রত্যেকটা event-এর হিসাব দিতে হয়। আর টাকার হিসাব এদিক-ওদিক হলেই bank-এর liability তৈরি হয়ে যাবে। Bank-এর reputation নষ্ট হবে। এই জন্য এই জিনিসটা খুবই important। Similar way-তে medical related application-এর জন্যও same rule apply হতে পারে।&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complete Audit Trail&lt;/strong&gt; — কখন কী হয়েছে সব জানা যাবে। Financial system, healthcare-এ এটা must।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal Query&lt;/strong&gt; — "৩ মাস আগে balance কত ছিল?" — সহজেই বের করা যাবে।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug&lt;/strong&gt; — Bug হলে event replay করে ঠিক কোথায় সমস্যা হয়েছে দেখা যাবে।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Replay&lt;/strong&gt; — নতুন feature-এর জন্য পুরনো data নতুন করে process করা যাবে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;কিন্তু এখানে একটা বড় question আসতে পারে, event-এর পরিমাণ যদি ১ লাখের বেশি হয়ে যায় তখন কী হবে? প্রতিবার balance জানার জন্য ১ লাখ event replay করতে হবে? বিষয়টা কী পরিমাণ resource consume করতে পারে সেটা বুঝতেই পারছেন।&lt;br&gt;
Answer হচ্ছে এটা বারবার করার প্রয়োজন হবে না। এর জন্য &lt;strong&gt;Snapshots&lt;/strong&gt; use করা হয়।&lt;/p&gt;


&lt;h2&gt;
  
  
  Snapshots
&lt;/h2&gt;

&lt;p&gt;Snapshots concept-এর সাথে already পরিচিত হওয়ার কথা। সংক্ষেপে বললে এখানে কিছু checkpoints তৈরি করে রাখা হয়, যাতে easily সেগুলো use করা যায়।&lt;/p&gt;

&lt;p&gt;ওপরে যে problem-টার কথা বললাম, ১ লাখ event হলে কী হবে। আসলে এই ক্ষেত্রে snapshot use করা হবে। প্রতি ১০০০ event-এর state-কে aggregate-এ save করে রাখা হবে snapshot হিসেবে। এভাবে চলতে থাকবে।&lt;/p&gt;

&lt;p&gt;তখন ১ লাখ event-এর জন্য, last snapshot এবং নতুন events-গুলো replay করলেই হয়ে যাবে। Balance জেনে যাবো।&lt;/p&gt;


&lt;h2&gt;
  
  
  Projection: Read Model তৈরি করুন
&lt;/h2&gt;

&lt;p&gt;এখানে যেহেতু কোনো single state না। আপনি চাইলেই এটাকে direct present করতে পারবেন না। এটাকে present করার জন্য কিছু কাজে লাগবে। সেই জিনিসটা হচ্ছে &lt;strong&gt;Projection (বা Projector Engine)&lt;/strong&gt; । আর এই projection-এর মাধ্যমে read optimized view তৈরি করা হয়।&lt;/p&gt;

&lt;p&gt;Projector ব্যাকগ্রাউন্ডে Event Store থেকে আসা নতুন ইভেন্টগুলো শোনে (Event Bus/Kafka-র মাধ্যমে) এবং সরাসরি &lt;strong&gt;Read Database&lt;/strong&gt;-এ pre-computed বা সাজানো ডাটা আপডেট করে দেয়&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Projector যা Read Database আপডেট করে&lt;/span&gt;
&lt;span class="nx"&gt;eventBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OrderPlaced&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;readDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userDashboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;$inc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;totalOrders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;totalSpent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;$set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lastOrderAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  কখন ব্যবহার করবেন?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CQRS+Event Sourcing দরকার যখন:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Audit log mandatory (banking, healthcare, legal)&lt;/li&gt;
&lt;li&gt;Complex reporting/analytics&lt;/li&gt;
&lt;li&gt;High read/write ratio difference&lt;/li&gt;
&lt;li&gt;Event replay দরকার হবে&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;দরকার নেই যখন:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple CRUD application&lt;/li&gt;
&lt;li&gt;Small team, fast iteration&lt;/li&gt;
&lt;li&gt;History রাখার দরকার নেই&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;CQRS আর Event Sourcing powerful কিন্তু complexity আনে। Simple CRUD-এ এটা over-engineering। কিন্তু financial system, audit trail critical এমন system-এ — এটা ছাড়া চিন্তাই করা যায় না।&lt;/p&gt;

&lt;p&gt;আপনি চাইলে শুধু cqrs pattern use করতে পারেন, যদি application-এর scale ছোট হয়। তবে complex এপ্লিকেশন এ দুই টা জিনিস একসাথেই বেশির ভাব ক্ষেত্রেই use হয়।&lt;/p&gt;

&lt;p&gt;CQRS বা Event Sourcing কি আপনার কাজে লেগেছে? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>database</category>
      <category>performance</category>
      <category>scalability</category>
    </item>
    <item>
      <title>Day 23 - Domain-Driven Design - কোড যখন Business-এর ভাষায় কথা বলে</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Mon, 28 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-23-domain-driven-design-kodd-ykhn-business-er-bhaassaay-kthaa-ble-106a</link>
      <guid>https://dev.to/mislam-dev/day-23-domain-driven-design-kodd-ykhn-business-er-bhaassaay-kthaa-ble-106a</guid>
      <description>&lt;p&gt;আপনার application এখন অনেক বড় হয়েছে। আপনি microservices বা modular monolith নিয়ে কাজ করছেন। সবকিছু ঠিকঠাকই চলছে, কিন্তু নতুন একটা সমস্যা দেখা দিলো।&lt;/p&gt;

&lt;p&gt;Business team মিটিংয়ে বলছে, "যখন কোনো VIP Customer-এর Order confirm হবে, তখন তার Loyalty Points add করতে হবে এবং Inventory থেকে Stock reserve করতে হবে।"&lt;/p&gt;

&lt;p&gt;কিন্তু আপনার codebase-এ গিয়ে দেখলেন &lt;code&gt;VIP Customer&lt;/code&gt; বা &lt;code&gt;Loyalty Points&lt;/code&gt; নামে কিছুই নেই! সেখানে আছে &lt;code&gt;UserEntity&lt;/code&gt;, &lt;code&gt;status_flag = 1&lt;/code&gt;, আর &lt;code&gt;OrderRepository&lt;/code&gt;।&lt;br&gt;
Business team-এর ভাষা আর developer-দের কোডের ভাষার মধ্যে বিশাল গ্যাপ। এই গ্যাপের কারণেই complex project-এ bug বেশি আসে এবং requirement বুঝতে ভুল হয়।&lt;/p&gt;

&lt;p&gt;এই সমস্যার সমাধানই হলো &lt;strong&gt;DDD (Domain-Driven Design)&lt;/strong&gt;।&lt;/p&gt;


&lt;h2&gt;
  
  
  Domain-Driven Design (DDD) কী?
&lt;/h2&gt;

&lt;p&gt;সহজ কথায়, Domain-Driven Design (DDD) হলো সফটওয়্যার তৈরির এমন একটি অ্যাপ্রোচ, যেখানে ডাটাবেস বা ফ্রেমওয়ার্কের চেয়ে &lt;strong&gt;Business Domain&lt;/strong&gt; বা ব্যবসার মূল লজিককে বেশি গুরুত্ব দেওয়া হয়।&lt;/p&gt;

&lt;p&gt;সাধারণত আমরা ডাটাবেস টেবিল চিন্তা করে কোড লেখা শুরু করি (Data-Driven)। কিন্তু DDD-তে আমরা আগে Business-এর কাজগুলো (Domain) বুঝি এবং সেই অনুযায়ী কোড সাজাই। এর মূল লক্ষ্য হলো ডেভেলপার এবং ডোমেইন এক্সপার্টদের (business team) মধ্যে দূরত্বের অবসান ঘটানো এবং কোডকে এমনভাবে স্ট্রাকচার করা যেন তা বাস্তব জগতের business process-এর সাথে হুবহু মিলে যায়।&lt;/p&gt;


&lt;h2&gt;
  
  
  Ubiquitous Language: একই ভাষায় কথা বলুন
&lt;/h2&gt;

&lt;p&gt;DDD-র প্রথম নিয়ম - developer আর business stakeholder একই শব্দ ব্যবহার করবে।&lt;/p&gt;

&lt;p&gt;Business যদি বলে "Order confirm করো", codebase-এও ঠিক &lt;code&gt;order.confirm()&lt;/code&gt; মেথড থাকবে।&lt;br&gt;
Business যদি বলে "Customer", কোডে &lt;code&gt;User&lt;/code&gt; না লিখে &lt;code&gt;Customer&lt;/code&gt; লিখতে হবে।&lt;/p&gt;

&lt;p&gt;এই common vocabulary-কে বলে &lt;strong&gt;Ubiquitous Language&lt;/strong&gt;। যখন code এবং business একই ভাষায় কথা বলে, তখন requirement implement করা অনেক সহজ হয়ে যায়।&lt;/p&gt;


&lt;h2&gt;
  
  
  Bounded Context: সীমানা টানুন
&lt;/h2&gt;

&lt;p&gt;একটা বড় system-এ একই শব্দের মানে ভিন্ন ভিন্ন জায়গায় ভিন্ন হতে পারে।&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sales context-এ Customer = নাম, contact, purchase history।&lt;/li&gt;
&lt;li&gt;Shipping context-এ Customer = delivery address, preferred time।&lt;/li&gt;
&lt;li&gt;Support context-এ Customer = ticket history, complain log।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এগুলো হলো &lt;strong&gt;আলাদা Bounded Context&lt;/strong&gt;। প্রতিটা context-এ "Customer" একটু আলাদা মডেল।&lt;br&gt;
এটা না বুঝলে একটা God-object তৈরি হয় - মানে ২,০০০ লাইনের একটা বিশাল &lt;code&gt;User&lt;/code&gt; class যেখানে সব context-এর logic একসাথে ভরা থাকে। Microservices-এ সার্ভিস ভাগ করার ক্ষেত্রে এই Bounded Context-ই সবচেয়ে বড় ভূমিকা পালন করে।&lt;/p&gt;


&lt;h2&gt;
  
  
  Entity vs Value Object: ডেটার ধরন বুঝুন
&lt;/h2&gt;

&lt;p&gt;DDD-তে object সাধারণত দুই ধরনের হয়:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;১. Entity:&lt;/strong&gt; যার একটা Unique ID আছে এবং সময়ের সাথে যার state পরিবর্তন হয়। যেমন: &lt;code&gt;Order&lt;/code&gt;, &lt;code&gt;Customer&lt;/code&gt;। এদের ID এক হলে properties ভিন্ন হলেও এরা একই Entity।&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;২. Value Object:&lt;/strong&gt; যার কোনো ID নেই, এর value দিয়েই একে চেনা হয়। যেমন: &lt;code&gt;Address&lt;/code&gt;, &lt;code&gt;Money&lt;/code&gt;।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Money&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Currency mismatch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Value objects সবসময় Immutable হয়।&lt;/p&gt;




&lt;h2&gt;
  
  
  Aggregate: Consistency-র দারোয়ান
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Aggregate&lt;/strong&gt; হলো একটা cluster of objects (Entities and Value Objects) যেটা একসাথে consistent থাকতে হবে।&lt;/p&gt;

&lt;p&gt;যেমন, &lt;code&gt;Order&lt;/code&gt; হলো একটা Aggregate (একে Aggregate Root-ও বলা যায়)। এর ভেতরে &lt;code&gt;OrderItems&lt;/code&gt;, &lt;code&gt;ShippingAddress&lt;/code&gt; (Value Object) থাকতে পারে। বাইরের কোনো class সরাসরি &lt;code&gt;OrderItem&lt;/code&gt;-কে modify করতে পারবে না, যা করার &lt;code&gt;Order&lt;/code&gt;-এর মাধ্যমেই করতে হবে।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OrderStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;OrderStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PENDING&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Business logic inside the domain, not in a service!&lt;/span&gt;
  &lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;OrderStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PENDING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot modify a confirmed order&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot confirm an empty order&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;OrderStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CONFIRMED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDomainEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderConfirmedEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Business rule কোডের ভেতরে থাকবে, Controller বা Service layer-এ নয়।&lt;/p&gt;




&lt;h2&gt;
  
  
  Domain Events: যা ঘটলো সেটা জানাও
&lt;/h2&gt;

&lt;p&gt;যখন কোনো Aggregate-এর state change হয়, তখন সে একটা event fire করে। Event-Driven Architecture (EDA)-এর সাথে এটি চমৎকারভাবে কাজ করে।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderConfirmedEvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;occurredAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Order.confirm()&lt;/code&gt; call হলে &lt;code&gt;OrderConfirmedEvent&lt;/code&gt; fire হবে। এরপর Email module বা Inventory module যে-ই এই event শুনুক না কেন, সে তার নিজের কাজ (Bounded context-এর ভেতরের কাজ) স্বাধীনভাবে করতে পারবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository Pattern: Data Access-এর আড়াল
&lt;/h2&gt;

&lt;p&gt;Domain object কীভাবে database-এ save হয়, সেটা Domain-এর জানার দরকার নেই। Domain layer থাকবে একদম pure, কোনো framework-এর dependency ছাড়া।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Domain Layer (Pure TypeScript)&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;OrderRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interface থাকবে Domain layer-এ, আর এর implementation থাকবে Infrastructure layer-এ।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Infrastructure Layer&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostgresOrderRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OrderRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;OrderSchema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OrderSchema&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Convert pure Domain 'Order' to TypeORM entity and save&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapToOrmEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এতে করে কালকে যদি ORM চেঞ্জও করেন, আপনার core business logic-এ এক লাইনেরও পরিবর্তন আসবে না!&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;DDD মানে complex architecture জোর করে চাপানো না। মানে হলো - code যেন business-এর ভাষায় কথা বলে, business rules যেন code-এ স্পষ্ট থাকে। ছোট CRUD application-এর জন্য DDD over-engineering, কিন্তু complex domain-এ এটা রক্ষাকবচ।&lt;/p&gt;

&lt;p&gt;DDD-এর কোন concept-টা আপনার কাছে সবচেয়ে interesting লেগেছে? Entity নাকি Value Object? কমেন্টে বলুন! 👇&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>microservices</category>
      <category>software</category>
    </item>
    <item>
      <title>Day 22 — Microservices vs Monolith — Hype বাদ দিয়ে সত্যিটা বলি</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Sun, 27 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-22-microservices-vs-monolith-hype-baad-diye-styittaa-bli-3872</link>
      <guid>https://dev.to/mislam-dev/day-22-microservices-vs-monolith-hype-baad-diye-styittaa-bli-3872</guid>
      <description>&lt;p&gt;আপনার application এখন ভালোভাবেই চলছে। আপনি এখন আর একা কাজ করেন না। আপনি কয়েকটি team build করেছেন। অনেকদিন ধরেই এই team building-টা চলছে। মোটামুটি ১০০-১২০ জনের team আপনারা operate করছেন।&lt;/p&gt;

&lt;p&gt;এখন আপনার ইচ্ছা জাগল যে system-টা optimize করা দরকার। এর জন্য শুরু করলেন system monitoring। এভাবে ১ সপ্তাহ monitoring করলেন। ১ সপ্তাহ পর আপনার কাছে সব data চলে আসলো। আপনি কিছু জিনিস খেয়াল করলেন:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feed এবং Chat related service-গুলো সবথেকে বেশি use হচ্ছে।&lt;/li&gt;
&lt;li&gt;Post-এর write-এর থেকে read করা হচ্ছে বেশি।&lt;/li&gt;
&lt;li&gt;Payment related service-গুলোর usage একেবারেই কম, মাসের শেষে বা প্রথমে এই service-টা use হয়।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এছাড়াও আরও কিছু জিনিস আপনি উপলব্ধি করলেন, team member-দের কাছ থেকে feedback নিলেন:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feed related service-গুলো, post-এর সাথে সম্পৃক্ত থাকলেও, chat related service-এর কোনো connection নেই। এই কারণে অনেক performance drop হচ্ছে। Server capacity বেড়ে যাচ্ছে। বেশি user handle করা যাচ্ছে না। For example, সন্ধ্যার পরে chat service-এর usages বেড়ে যায়, এই কারণে user-রা নতুন post করতে problem face করে, অল্প একটু latency থাকে। Feed service-এ একটু problem হয়।&lt;/li&gt;
&lt;li&gt;Development problem। Application-টা অনেক বড় হয়ে গেছে। এখন একই codebase-এ অনেক team কাজ করে। এই জন্য এটা maintain করা ঝামেলা হয়ে যাচ্ছে। Feature development-এর চেয়ে code maintain করতেই সময় চলে যাচ্ছে।&lt;/li&gt;
&lt;li&gt;Deployment issue। Everyday নতুন নতুন feature, improvement হচ্ছে। এই অবস্থায় ছোট একটা bug fix করে deploy করলেও পুরো application build করা লাগছে।&lt;/li&gt;
&lt;li&gt;Merge conflict নিয়মিত হচ্ছে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এগুলো ছাড়াও আরও অনেক বিষয় আছে যেগুলো আপনি উপলব্ধি করলেন। এই কারণে system-এর performance down হচ্ছে। একটু optimize করলে profit-ও একটু বাড়ানো যাবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Monolith: যা দিয়ে সবাই শুরু করে
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Monolith&lt;/strong&gt; মানে সব কিছু একটা codebase-এ, একটা deployment। আপনার application-টাও কিন্তু monolith application। Server অনেকগুলো বাড়িয়েছেন কিন্তু codebase তো সেই একটাই।&lt;/p&gt;

&lt;p&gt;Monolith application's folder structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-app/
  ├── auth/
  ├── orders/
  ├── payments/
  ├── notifications/
  └── main.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;সুবিধা:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development simple। একটা project খুললেই সব দেখা যায়।&lt;/li&gt;
&lt;li&gt;Debugging easy।&lt;/li&gt;
&lt;li&gt;End-to-end test সহজ।&lt;/li&gt;
&lt;li&gt;Deploy একটাই।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;সমস্যা যখন বাড়ে:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Codebase বিশাল হয়ে যায়।&lt;/li&gt;
&lt;li&gt;একটা bug পুরো app down করে।&lt;/li&gt;
&lt;li&gt;আলাদা আলাদা scale করা যায় না।&lt;/li&gt;
&lt;li&gt;৫০ জন developer একই codebase-এ conflict করে।&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Microservices: Small and Independent
&lt;/h2&gt;

&lt;p&gt;আপনার বর্তমান সমস্যার সমাধান হচ্ছে microservice। Application-কে domain এবং use case অনুযায়ী অনেক part-এ divide করা হবে। প্রত্যেকটা part-ই হলো একেকটা microservice। এখানে প্রত্যেকটা service standalone application হিসেবে কাজ করে। Logic আলাদা, implementation আলাদা হতে পারে, infact database-ও আলাদা হতে পারে।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feed-service     → port 3001
chat-service    → port 3002
payment-service  → port 3003
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;সুবিধা:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent deploy — Payment service update করলে feed বা chat service restart না।&lt;/li&gt;
&lt;li&gt;Independent scale — Feed page-এ বেশি traffic? শুধু feed-service scale করলেই হবে।&lt;/li&gt;
&lt;li&gt;আলাদা team আলাদা service own করে। এতে কোড maintain করা easy হয়। Merge conflict কমে যায়।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;সমস্যা:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network latency — একটা request ৫টা service ঘুরে আসে।&lt;/li&gt;
&lt;li&gt;Distributed transactions কঠিন।&lt;/li&gt;
&lt;li&gt;Debugging nightmare — কোন service-এ error?&lt;/li&gt;
&lt;li&gt;Infrastructure complexity বাড়ে অনেক।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এখানে একটা problem আছে। আগের multiple server-এর মতো। আগে তো Load Balancer use করে সেটা solve করেছিলাম। সেখানে একটা application-এর clone ছিল, problem নাই। কিন্তু এখানে Load Balancer দিয়ে কাজ হবে না।&lt;/p&gt;

&lt;p&gt;আর এই service-গুলোর IP address সব জায়গায় দেওয়া তো possible না। তাহলে solution-টা কী? Solution-টা হচ্ছে API Gateway। API Gateway-তে এই service-গুলো connect হবে এবং একটা simple application-এর মতো behave করবে। User কিছুই বুঝতে পারবে না।&lt;/p&gt;




&lt;h3&gt;
  
  
  যেখানে সবচেয়ে বেশি ক্যাচাল লাগে!
&lt;/h3&gt;

&lt;p&gt;Microservices মানে distributed system। আর আমি আগে বলেছি, "Distributed system is a nightmare"। কখন কোন সময় কী হবে আপনি predict-ই করতে পারবেন না। 3 body problem-এর মতো। আপনার ঘুম হারাম হয়ে যেতে পারে যেকোনো সময়।&lt;/p&gt;

&lt;p&gt;Problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partial failures&lt;/strong&gt; — Service A চলছে, Service B down। এখন আপনি সার্ভিস B use করতে পারবেন না। এখানে scalling করা লাগতে পারে। তার জন্য আলাদা ঝামেলা।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network timeouts&lt;/strong&gt; — কোনর কারণে নেটওয়ার্ক slow হয়ে গেছে, এক টা পর্যায়ে timeout ও হয়ে যাচ্ছে। এখন inter-service communication করতে সমস্যা হবে ইনফ্যাক্ট হবেই না। এটা একটা সমস্যা।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data consistency&lt;/strong&gt; — দুই service-এ data কীভাবে consistent রাখব? এর জন্য CAP theoram আছে। এই নিয়ে সামনে আলোচনা হবে ইনশাআল্লাহ।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এই problem গুলা resolve করতে Circuit Breaker, Saga pattern, Distributed tracing — সব দরকার। এই overhead ছোট team সামলাতে পারে না। এই জন্য ছোট টিমের জন্য microservice না।&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;N:B: এতক্ষণে হয়তো কিছু idea করতে পেরেছেন যে microservice-এ event driven architecture কেন use করা হয়।&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  কখন কোনটা?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Monolith দিয়ে শুরু করুন যখন:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Startup, নতুন product, MVP।&lt;/li&gt;
&lt;li&gt;Team size ছোট (&amp;lt; ১৫ জন)।&lt;/li&gt;
&lt;li&gt;Business domain এখনো পরিষ্কার না।&lt;/li&gt;
&lt;li&gt;Fast iteration দরকার।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Microservices যান যখন:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product proven, scale দরকার।&lt;/li&gt;
&lt;li&gt;Team বড় (৫০+ developer)।&lt;/li&gt;
&lt;li&gt;স্পষ্ট bounded context আছে।&lt;/li&gt;
&lt;li&gt;Independent deploy-এর সুবিধা cost justify করে।&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Modular Monolith: Middle Ground
&lt;/h2&gt;

&lt;p&gt;Monolith-এ সবকিছু তো এক জায়গাতেই থাকে। Modular monolith-এ সব code একসাথেই থাকে তবে সেগুলো module আকারে divide করা থাকে। অনেকটা microservice-এর concept-এর মতো, standalone module। এইসব module-গুলো main application-এর সাথে loosely coupled থাকে। খুব easily এই application থেকে module remove করা যায় বা অন্য কোথাও সরিয়ে নিয়ে যাওয়া যায়।&lt;/p&gt;

&lt;p&gt;আমি personally modular monolith architecture-টা পছন্দ করি।&lt;/p&gt;

&lt;p&gt;Folder structure of Modular Monolth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-app/
  ├── modules/
  │   ├── auth/      ← নিজস্ব DB schema
  │   ├── orders/    ← নিজস্ব DB schema
  │   └── payments/  ← নিজস্ব DB schema
  └── main.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modular monolith-এর সবথেকে বড় সুবিধা হচ্ছে, এই module-গুলোকে gradually microservices-এ convert করা যায়। For example, order-কে আমি একটা আলাদা service-এ নিয়ে যেতে পারবো। একটা standalone application বানাবো এবং feature সবকিছু same থাকবে। At last, API Gateway-এর সাথে main application + order service connect করে দেবো। এভাবে gradually একটা modular monolith-কে microservice-এ transfer করা যায়।&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;Microservices Netflix, Uber-এর জন্য সঠিক — কারণ তারা সেই scale-এ। startup-এর জন্য না। Monolith দিয়ে শুরু করুন, domain বুঝুন, তারপর দরকার হলে আলাদা করুন।&lt;/p&gt;

&lt;p&gt;আপনার current project কোনটা? পরিবর্তন করেছেন কখনো? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Day 21 - Scaling - Horizontal vs Vertical Scaling - কোনটা কখন করবেন?</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Sat, 26 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-21-scaling-horizontal-vs-vertical-scaling-konttaa-kkhn-krben-ge7</link>
      <guid>https://dev.to/mislam-dev/day-21-scaling-horizontal-vs-vertical-scaling-konttaa-kkhn-krben-ge7</guid>
      <description>&lt;p&gt;আপনার build করা application-টি এতই viral হয়ে গেছে যে, এর user base lakh cross করে গেছে। এবং concurrent user লাখের কাছাকাছি। এই অবস্থায় আপনার যে server আছে, তা user-দের load নিতে পারছে না। Peak time-এ user-দের wait করতে হচ্ছে। Data inconsistency-র একটা issue দেখা দিচ্ছে। মাঝে মাঝে server crash করছে। মাঝে মাঝে database-এ data insert হচ্ছে না। অবস্থা একদম বেগতিক হয়ে গেছে।&lt;/p&gt;

&lt;p&gt;এখন এর সমাধান হচ্ছে resource বাড়ানো। সহজ কথায় scale করা। আপনি ঠিক তাই করলেন, scale করে resource বাড়িয়ে দিলেন—user খুশি, আপনিও খুশি।&lt;/p&gt;

&lt;p&gt;কিন্তু সমস্যা বাঁধল কিছুদিন পর। আপনার আগে যে concurrent user ছিল লাখের কাছাকাছি, সেটা 1 million ছাড়িয়ে গেল। আবার সেই আগের মতো situation তৈরি হলো। আপনি resource বাড়াতে গিয়ে দেখলেন যে, আপনার server-এর resource limit শেষ। মানে আর increase করতে পারবেন না।&lt;/p&gt;

&lt;p&gt;এখন কী করবেন?&lt;/p&gt;

&lt;p&gt;আসুন, এই বিষয়গুলো নিয়েই আলোচনা করি।&lt;/p&gt;




&lt;h2&gt;
  
  
  Vertical Scaling: A single big machine
&lt;/h2&gt;

&lt;p&gt;Vertical scaling সহজভাবে বললে, আপনার machine থাকবে একটা। আমি শুধু এর CPU, memory, storage এগুলো increase করব। এই কাজটা কিন্তু already দুইবার করে ফেলেছেন। এটাই হলো vertical scaling।&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core: আগে ২, এখন ৪&lt;/li&gt;
&lt;li&gt;Memory: আগে 8GB, এখন 16GB&lt;/li&gt;
&lt;li&gt;Storage: আগে 50GB, এখন 100GB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;সুবিধা:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple। Application-এ কোনো পরিবর্তন লাগে না।&lt;/li&gt;
&lt;li&gt;Database-এর জন্য অনেক সময় সহজতম সমাধান।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;সমস্যা:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;একটা সীমা আছে। সবচেয়ে বড় server-ও finite। এই সম্মুখীন already হয়ে গেছেন।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Point of Failure&lt;/strong&gt; - এই একটা server dead হয়ে গেলে সব বন্ধ হয়ে যাবে।&lt;/li&gt;
&lt;li&gt;Downtime লাগতে পারে upgrade করতে।&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Horizontal Scaling: Multiple Machine
&lt;/h2&gt;

&lt;p&gt;Vertical scaling-এ একটা machine-এই শুধু resource increase করা হয়েছে। Horizontal scaling-এর ক্ষেত্রে এটা পুরোটাই উল্টো। এখানে resource increase করার বদলে নতুন machine introduce করা হয়। Theoretically, এই machine-এর সংখ্যা unlimited। মূলত user traffic-কে এই machine-গুলোতে distribute করে দেয়া হবে। এতে machine-এর ওপর load কমে গেলে ভালোভাবে perform করতে পারবে।&lt;/p&gt;

&lt;p&gt;আপনি একটু চালাক আছেন, তাই আপনার মনে question জাগলো—যে ২-১টা machine-এর IP address তো আমি manually distribute করতেই পারি। কিন্তু machine বা server যদি ১০, ২০ বা তার অধিক হয়, তাহলে তো ঝামেলা বেধে যাবে!&lt;/p&gt;

&lt;p&gt;এর solution হচ্ছে Load Balancer। Load Balancer-এর কাজ হচ্ছে user traffic-কে multiple server-এর ভেতর distribute করে দেয়া।&lt;br&gt;
এখন আপনি নিশ্চিন্ত।&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;সুবিধা:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Theoretically unlimited scaling।&lt;/li&gt;
&lt;li&gt;একটা server deah হলেও বাকিগুলো চলতে থাকে।&lt;/li&gt;
&lt;li&gt;Traffic বাড়লে server বাড়ানো জয়, কমলে server কমানোও যায়।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;সমস্যা:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application-কে &lt;strong&gt;stateless&lt;/strong&gt; হতে হবে।&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Applicaiton with session based authentication is a Statefull apllication.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Stateless হওয়া কেন দরকার?
&lt;/h3&gt;

&lt;p&gt;মনে করুন আপনার application authentication-এর জন্য session use করে।&lt;br&gt;
আপনার system-এ ৩টি server আছে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server A&lt;/li&gt;
&lt;li&gt;Server B&lt;/li&gt;
&lt;li&gt;Server C&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এখন user login করার জন্য login route-এ hit করলো, এটা Load Balancer (LB)-এর কাছে আসলো, তারপর LB সেটাকে Server A-তে redirect করে দিলো। Server-এ session create হলো। এই পর্যন্ত ঠিকই আছে।&lt;/p&gt;

&lt;p&gt;এরপর login করার পর user dashboard open করলো (dashboard public user-দের জন্য restricted), dashboard-এর জন্য server-এ request গেলো। প্রথমে LB-র কাছে, LB এবার request-টাকে Server B-তে redirect করলো। Server B দেখলো যে এখানে কোনো session-ই নাই। তারমানে এ public user, একে data দেয়া যাবে না। আপনার request reject করে দিলো এবং dashboard আর load হলো না।&lt;/p&gt;

&lt;p&gt;এখন session-based authentication যদি খুব বেশি important হয়, তাহলে এর জন্য একটা solution আছে। Session store করার জন্য একটা আলাদা database use করতে হবে। এই database Redis হতে পারে।&lt;/p&gt;

&lt;p&gt;Redis use করার সবচেয়ে বড় reason হচ্ছে এর TTL (Time To Live) based expiration। আপনার session তো একটা নির্দিষ্ট সময়ে গিয়ে expire হয়ে যাবে। Redis আপনাকে সেটা by default-ই দিয়ে দিবে, আপনাকে manually delete করতে হবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Database Scaling: আলাদা চিন্তা
&lt;/h2&gt;

&lt;p&gt;আপনার সামনে নতুন একটা situation তৈরি হয়ে গেছে। ১০টা server তো add করে দিলেন, কিন্তু user-কে সেই wait করতেই হচ্ছে। আপনি একটু investigate করার পর বুঝতে পারলেন যে, এখন server problem না করলেও database problem করা শুরু করে দিয়েছে।&lt;/p&gt;

&lt;p&gt;Server-এর load distribute হলেও, database-এর load কিন্তু সেই আগের মতোই আছে। এখন database-কেও scale করা লাগবে। তবে server-এর মতো database scaling এত easy না। একটু এদিক-সেদিক হলেই আপনার পুরো system-এ সমস্যা হতে পারে, user data গায়েব হয়ে যেতে পারে। Data inconsistency দেখা দিতে পারে। এছাড়াও আরও অনেক রকম problem আছে।&lt;/p&gt;

&lt;p&gt;Database scaling-এর ক্ষেত্রে mainly vertical scaling যতটা possible করা হয়। তারপরেও যদি problem হয়, তাহলে-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vertical Scaling&lt;/strong&gt; - একটাই big powerful server।&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read Replica&lt;/strong&gt; - Read operations এর জন্য বাড়তি database server add করা।&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sharding&lt;/strong&gt; - শুধু যখন সত্যিই দরকার। এটা নিয়ে পুরা একটা বই লিখে ফেলা যাবে।&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;তবে ক্ষেত্রবিশেষে caching করলেই database scaling করা লাগে না। For example, read-heavy application-এ database-এ load-ই আসবে না। Cache থেকেই সব data serve হয়ে যাবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Types of Scaling একসাথে
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Load Shifting&lt;/strong&gt; - Peak time-এর কাজ off-peak-এ করো। Batch jobs রাতে।&lt;br&gt;
&lt;strong&gt;Auto Scaling&lt;/strong&gt; - Traffic বাড়লে automatically নতুন instance, কমলে বন্ধ। AWS, GCP সব দেয়।&lt;/p&gt;




&lt;h2&gt;
  
  
  কোনটা করব?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;পরিস্থিতি&lt;/th&gt;
&lt;th&gt;পদ্ধতি&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Database bottleneck&lt;/td&gt;
&lt;td&gt;Vertical scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web server bottleneck&lt;/td&gt;
&lt;td&gt;Horizontal scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sudden traffic spike&lt;/td&gt;
&lt;td&gt;Auto-scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Budget কম&lt;/td&gt;
&lt;td&gt;Vertical দিয়ে শুরু&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High availability দরকার&lt;/td&gt;
&lt;td&gt;Horizontal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;শুরুতে Vertical scaling। সহজ, কোড পরিবর্তন লাগে না। তারপর stateless architecture বানান, তখন Horizontal scaling সহজ হয়ে যায়। Database আলাদাভাবে চিন্তা করুন।&lt;/p&gt;

&lt;p&gt;আপনার system-এ এখন কোন scaling strategy? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>scalability</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Day 20 — CDN ও Edge Caching — সার্ভারকে বিশ্রাম দিন</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Fri, 25 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-20-cdn-o-edge-caching-saarbhaarke-bishraam-din-56gp</link>
      <guid>https://dev.to/mislam-dev/day-20-cdn-o-edge-caching-saarbhaarke-bishraam-din-56gp</guid>
      <description>&lt;p&gt;আপনি অনেক কষ্ট করে একটি application develop করলেন। Deploy করলেন বাংলাদেশের একটি server-এ। খুব সুন্দরভাবে সবকিছু চলছিল। কিন্তু হঠাৎ করে আপনার এই application-টি viral হয়ে গেল।&lt;/p&gt;

&lt;p&gt;এখন Australia থেকে কেউ আপনার application-টি try করতে চাইল। কিন্তু সবকিছু অনেক দেরিতে show হচ্ছে। Latency অনেক বেশি। মোটামুটি অনেক time লেগে যাচ্ছে, wait করতে হচ্ছে। HTTP কীভাবে কাজ করে, এটা বুঝতে পারলে, কেন এমন হচ্ছে তা সহজেই বুঝে যাবেন।&lt;/p&gt;

&lt;p&gt;বাংলাদেশ থেকে Australia-র distance প্রায় ৭,৫০০ কিলোমিটার। এখন এই distance অতিক্রম করতে সবকিছু মিলিয়ে মোটামুটি 300-500ms লেগে যাবে। Content-এর size অনুযায়ী এটা কমবেশি হতে পারে। Generally, এটা বেশ অনেকটা সময়। বাংলাদেশ থেকে Australia-তে data যেতেই এই সময় লেগে যাচ্ছে। এরপর locally load হওয়ার জন্যও আরও অনেক time লাগবে। এতে user কমে যাওয়ার সম্ভাবনা থাকে।&lt;/p&gt;

&lt;p&gt;এই latency কমানোর উপায় কী?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CDN (Content Delivery Network)&lt;/strong&gt;।&lt;/p&gt;




&lt;h2&gt;
  
  
  CDN কীভাবে কাজ করে?
&lt;/h2&gt;

&lt;p&gt;একটা বিষয় চিন্তা করে দেখুন, আপনি যখন বাংলাদেশ থেকে access করেন তখন কিন্তু খুব বেশি সময় লাগে না। মানে আপনি যখন server-এর কাছাকাছি থাকেন, তখন latency অনেক কম থাকে।&lt;/p&gt;

&lt;p&gt;কোনোভাবে, এই কাজটা যদি Australia-তেও করা যেত, তাহলে latency অনেকটাই কম হতো! কিন্তু সমস্যা হচ্ছে, Australia-তে same server maintain করা একটু ঝামেলার ব্যাপার।&lt;/p&gt;

&lt;p&gt;এই সমস্যাটার সমাধানই করে মূলত CDN।&lt;/p&gt;

&lt;p&gt;CDN হলো একটি distributed network যেখানে বিশ্বের বিভিন্ন স্থানে server স্থাপন করা থাকে এবং এই serverগুলো একসাথে কাজ করে। CDN data store করার পর স্বয়ংক্রিয়ভাবে সেই Data সব সার্ভারে Replicate হয়ে যাবে এবং সেখান থেকেই পরবর্তীতে ডাটা সার্ভ হবে।&lt;/p&gt;

&lt;p&gt;Australia থেকে request করা user Australia-র সব থেকে কাছের সার্ভার থেকে এই ডাটা পাবে।&lt;/p&gt;

&lt;p&gt;Setup করার পর latency 30-50ms-এর মধ্যে চলে আসবে। অর্থাৎ, প্রায় 10x faster!&lt;/p&gt;

&lt;p&gt;বলে রাখা ভালো CDN শুধুমাত্র cached data serve করে। আর আগের একটা আর্টিকেলে বলেছি যে data cache করা আছে সেই data change করলে cache invalidation করে নতুনভাবে data cache করতে হয়।&lt;/p&gt;




&lt;h2&gt;
  
  
  কী Cache করা যায়?
&lt;/h2&gt;

&lt;p&gt;আপনি চাইলেই সব ডাটা ক্যাশ করতে পারবেন না। কারণ এক্ষেত্রে Inconsistency দেখা দিতে পারে। Caching নিয়ে ১৫ এবং ১৬ নম্বর আর্টিকেলে বিস্তারিত আলোচনা আছে। ইতিমধ্যেই জেনে থাকার কথা।&lt;/p&gt;

&lt;p&gt;CDN-এ মূলত নিচের এই জিনিসগুলো ক্যাশ করা হয়ে থাকে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static assets&lt;/strong&gt; — images, CSS, JS, fonts। এগুলো সহজেই cache করা যায়।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML pages&lt;/strong&gt; — SSG (Static Site Generation) site-এ পুরো HTML cache করা যায়।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API responses&lt;/strong&gt; — read-heavy, rarely changing data।&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cache Headers: Browser আর CDN-কে বলুন
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: public, max-age=31536000, immutable
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;public&lt;/code&gt; — CDN cache করতে পারবে।&lt;br&gt;
&lt;code&gt;max-age=31536000&lt;/code&gt; — ১ বছর cache।&lt;br&gt;
&lt;code&gt;immutable&lt;/code&gt; — এই সময়ে content পাল্টাবে না।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: no-cache
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এটা মানে cache করা যাবে না। Login page, checkout page-এ এটা দিন।&lt;/p&gt;




&lt;h2&gt;
  
  
  CDN কোথায় ব্যবহার করবেন?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static Assets&lt;/strong&gt; — &lt;code&gt;/assets/logo.png&lt;/code&gt;, &lt;code&gt;/dist/bundle.js&lt;/code&gt; — এগুলো CDN-এ রাখুন।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js / Vercel&lt;/strong&gt; — Edge-এ render করে। দুর্দান্ত performance।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image Optimization&lt;/strong&gt; — Cloudinary, ImageKit — images resize, compress, format convert করে deliver করে।&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cache Invalidation on CDN
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Cache invalidation is a nightmare."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CDN-এ file update করলে পুরানো cache আটকে থাকবে।&lt;/p&gt;

&lt;p&gt;সমাধান — &lt;strong&gt;Cache Busting&lt;/strong&gt;। File-এর URL-এ hash দিন:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/assets/bundle.a3f9c2.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Content পাল্টালে hash পাল্টাবে। Browser/CDN নতুন file নামাবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;CDN শুধু performance না — cost কমায়, availability বাড়ায়, security দেয়। Static assets CDN ছাড়া রাখা মানে unnecessary origin server load। আজই Cloudflare বা AWS CloudFront দিয়ে setup করুন।&lt;/p&gt;

&lt;p&gt;আপনার project-এ CDN আছে? না থাকলে কেন না? কমেন্টে জানান! 👇&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Day 19 — Real-Time Communications | WebSockets vs SSE vs Long Polling</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Thu, 24 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-19-real-time-communications-websockets-vs-sse-vs-long-polling-4c96</link>
      <guid>https://dev.to/mislam-dev/day-19-real-time-communications-websockets-vs-sse-vs-long-polling-4c96</guid>
      <description>&lt;p&gt;আমার development journey শুরু হয়েছিল PHP দিয়ে। আর স্বাভাবিকভাবেই জানেন যে PHP দিয়ে data fetch করাতে হলে প্রত্যেক বার HTTP request করতে হতো। তখন আমি first time Facebook-এর messenger-এর chatting feature দেখে অবাক হয়েছিলাম। কোনো reload ছাড়াই message send এবং receive হচ্ছে।&lt;/p&gt;

&lt;p&gt;এই বিষয় টা নিয়ে একটু research করার পরে জানতে পারি এইটা asynchronous communication। Page reload ছাড়াই server request পাঠানো যায়। এইটা মূলত করা HTTP request দিয়ে, যেমন এখন আমরা fetch বা axios দিয়ে করি।&lt;/p&gt;

&lt;p&gt;কিন্তু problem হচ্ছে, page reload ছাড়া অপর সাইডে message receive হয় না। একটু বিস্তারিত বলি, মনে করুন আপনি আপনার friend-কে message দিলেন, এখন এই http বা axios দিয়ে server-এ message দিলেন। এখন আপনার friend যতক্ষণ না তার page reload করছে ততক্ষণ এই message receive হবে না।&lt;/p&gt;

&lt;p&gt;কিন্তু আমি যেটা দেখেছিলাম, সেটা কিন্তু সম্পূর্ণ achieve করা হয়নি। Just ৫০% achieve হয়েছে মাত্র। এই জন্য আরেকটু research করি। তখন জানতে পারি আমি এতক্ষণ যেটা try করছিলাম, সেটা হচ্ছে ১-way communication কিন্তু আমাদের দরকার ২-way communication। এটা নিয়ে deep dive করলে জানতে পারি যে ২-way communication-এর জন্য WebSocket use করা হয়। আর WebSocket real-time-এ communicate করতে পারে। Reload করা ছাড়াও message send এবং receive করা যায়।&lt;/p&gt;




&lt;h2&gt;
  
  
  WebSocket কী?
&lt;/h2&gt;

&lt;p&gt;WebSocket হলো একটা communication-এর method যেখানে server এবং client always connected থাকে। এই connection close হয় না। Typical HTTP request-এ client-এর কিছু দরকার হলে, server-এ request পাঠায় তখন connection start হয়, data receive হয়ে গেলে এই connection close হয়ে যায়। কিন্তু WebSocket-এ এই connection-টা close হয় না। Always connected থাকে।&lt;/p&gt;

&lt;p&gt;WebSocket-এর use case ওপরের কথাতেই বুঝে যাওয়ার কথা। এ ছাড়াও আরও অনেক use case আছে।&lt;/p&gt;




&lt;h3&gt;
  
  
  WebSocket-এর সমস্যা
&lt;/h3&gt;

&lt;p&gt;মনে করুন, একটা গেমের leaderboard। এখানে কোন player-এর position কত সেটা live দেখাবে। এখানে যে দেখবে, সে হচ্ছে client। এখন আপনার কাছে প্রশ্ন, "Client তো শুধু দেখছে, সে আর input দিচ্ছে না। তাহলে এখানে যদি WebSocket use করি তাহলে কি ভালো হবে?"&lt;/p&gt;

&lt;p&gt;উত্তর দেওয়ার আগে একটা জিনিস বোঝার চেষ্টা করি। WebSocket ২-way communication-এর জন্য use হয়। কিন্তু এখানে লাগছে ১-way। Server শুধু data push করবে। Client end থেকে data push করার দরকার নেই। তাহলে এখানে WebSocket use করলে কিছু waste হবে। Resource-এর proper use হবে না। তাহলে মোদ্দা কথা হচ্ছে, WebSocket ideal solution না। তাহলে solution-টা কী?&lt;/p&gt;

&lt;p&gt;Solution-এ যাওয়ার আগে, এই টাইপের real-time communication-এর জন্য অনেকগুলো method আছে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Time Communication Methods
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Short Polling
&lt;/h3&gt;

&lt;p&gt;এই method-এ, একটা সময় (short time) পর পর server-এ request পাঠিয়েই যাবে এবং data update করবে। নিচের example-টা দেখুন:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/messages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// প্রতি ২ সেকেন্ডে&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে প্রতি ২ সেকেন্ড পর পর server-এ request পাঠাচ্ছে কোনো message আছে কিনা। এই method-টা ভালোই তবে এখানে কিছু problem আছে। যেমন,&lt;br&gt;
যদি server-এ নতুন কোনো message আসেনি, তাহলে কি request করার দরকার আছে? নেই। কিন্তু এই method-এ এটা হবে। Server-এ নতুন কোনো message আছে কিনা তা নিয়ে এই method-এর কোনো মাথাব্যথা নেই। এই method-এ request প্রতি ২ সেকেন্ড পর পর যেতেই থাকবে।&lt;br&gt;
এখন এই unnecessary request-এর জন্য server-এ load বাড়বে + bandwidth-ও নষ্ট হবে। বিষয়টা মনে হতে পারে খুব একটা problematic না। কিন্তু যখন user ১ মিলিয়নে চলে যাবে তখন এই ২ সেকেন্ডের unnecessary request আপনার server down হওয়ার main reason হবে।&lt;/p&gt;


&lt;h3&gt;
  
  
  Long Polling: একটু চালাক
&lt;/h3&gt;

&lt;p&gt;Long Polling, Short Polling-এর থেকে একটু চালাক। Short Polling তো interval পর পর request দিচ্ছে। কিন্তু Long Polling-এ server বলে, "তুমি আমার কাছে request দাও, দিয়ে তুমি wait করো, যখনই নতুন data আসবে তখন আমি তোমাকে response করব। তারপর তুমি যা খুশি করো।" নিচের example দেখুন:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/messages/wait&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Server hold করে রাখে&lt;/span&gt;
  &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// আবার শুরু&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এটা Short Polling-এর problem কিছুটা solve করলেও নতুন problem নিয়ে আসে। যেমন, এই method server connection close করে না। আর close না করলে সেই connection-এর data RAM-এ store করে রাখে। এখন আপনার system concurrently ১০০০ user request handle করতে পারে। কিন্তু worst case-এ এই ১০০০ user-ই একই সাথে request করল। তখন কী হবে? আপনার server-এর memory শেষ, এর মানে পুরা server crash করবে। এ ছাড়াও client side-এও problem তৈরি হওয়ার possibility আছে।&lt;/p&gt;

&lt;p&gt;এটাকে অনেকটা real-time-এর মতো মনে হলেও technically ওই simple HTTP-কেই একটু logic দিয়ে use করা হচ্ছে। বিষয়টা অনেকটা এই রকম—খেজুরের রস জ্বাল দিয়ে গুড় তৈরি করা।&lt;/p&gt;




&lt;h2&gt;
  
  
  WebSockets: Two-way Communication
&lt;/h2&gt;

&lt;p&gt;WebSocket জিনিসটা কী সেটা তো already বুঝেই গেছেন। WebSocket HTTP protocol use করে না বললেই চলে। WebSocket communication-এ TCP protocol use করে। WebSocket শুধুমাত্র connection-এর জন্য একদম প্রথমে HTTP request send করে। Connection হয়ে গেলে WebSocket TCP-এর মাধ্যমে data transfer করে থাকে। নিচের example-টা দেখুন:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocketServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// সবাইকে broadcast&lt;/span&gt;
    &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Client&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://localhost:8080&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WebSocket জিনিসটা বাকিগুলোর থেকে একটু complex, reason-টা বুঝেই গেছেন। বাকিগুলোতে ১-way communication হয় আর এখানে ২-way communication।&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;কখন WebSocket ব্যবহার করবেন&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chat application&lt;/li&gt;
&lt;li&gt;Multiplayer game&lt;/li&gt;
&lt;li&gt;Collaborative editing (Google Docs)&lt;/li&gt;
&lt;li&gt;Live trading platform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;সহজভাবে বললে, যেখানে client এবং server দুই দিক থেকেই real-time input এবং output দরকার তখন এই WebSocket use করা হয়।&lt;/p&gt;




&lt;h2&gt;
  
  
  Server-Sent Events (SSE): One-way Push
&lt;/h2&gt;

&lt;p&gt;একটা ছোট question করি, আমার যদি শুধু ১-way communication লাগে—মানে এখানে server শুধু input দিবে বা নতুন data show করাবে real-time-এ, কিন্তু user-এর দিক থেকে কোনো input-এর দরকার হবে না, তখন কি WebSocket use করাটা ভালো হবে? ওপরে ঠিক এই টাইপের একটা problem-এর কথা বলেছিলাম।&lt;/p&gt;

&lt;p&gt;এই problem-টা address করার জন্য আসে &lt;strong&gt;Server-Sent Events (SSE)&lt;/strong&gt;। এই method-এ server client-এ data push করে আর client সেই data receive করে থাকে। Server-এ যখনই কোনো নতুন data আসে তখন server নতুন data-কে stream করে দেয় আর client সেটা receive করে use করে। নিচের example-টা দেখুন:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Server (NestJS)&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Sse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;sendEvents&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MessageEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Client&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;কখন SSE ব্যবহার করবেন&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live notifications&lt;/li&gt;
&lt;li&gt;News feed&lt;/li&gt;
&lt;li&gt;Progress updates&lt;/li&gt;
&lt;li&gt;Stock prices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SSE ওই টাইপের problem-এর জন্য better, যেখানে শুধুমাত্র server থেকে client-এ data আসে।&lt;/p&gt;

&lt;p&gt;এখন ওপরে যে problem-টার কথা বলেছিলাম, আপনার মতে কোন method-টা use করলে better হবে?&lt;/p&gt;




&lt;h2&gt;
  
  
  সংক্ষেপে কোনটা কখন?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;পরিস্থিতি&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple notification&lt;/td&gt;
&lt;td&gt;SSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat, game&lt;/td&gt;
&lt;td&gt;WebSocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy system&lt;/td&gt;
&lt;td&gt;Long Polling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simple polling OK&lt;/td&gt;
&lt;td&gt;Short Polling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Real Life Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  সিনারিও:
&lt;/h3&gt;

&lt;p&gt;একটি ব্লগের আর্কিটেকচারের কথা চিন্তা করুন।&lt;/p&gt;

&lt;p&gt;ইউজার ফ্রন্টএন্ডে একটি নতুন পোস্ট তৈরি করল। এই সিস্টেমে ব্যবহার করা হয়েছে &lt;strong&gt;CQRS Pattern&lt;/strong&gt;।&lt;br&gt;
ফ্লো-টি কিছুটা এমন:&lt;br&gt;
&lt;code&gt;Frontend -&amp;gt; Post Service -&amp;gt; Write DB-তে Insert -&amp;gt; Kafka-তে Event Publish&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;এর পর &lt;code&gt;Query Service&lt;/code&gt; ওই Event রিসিভ করে Read DB-তে পোস্টটি সেভ করে।&lt;/p&gt;

&lt;p&gt;যেহেতু Read এবং Write-এর জন্য দুটো আলাদা সার্ভিস ও ডাটাবেস কাজ করছে, তাই ডাটা দুটো ডাটাবেসে সিঙ্ক (Sync) হতে কিছুটা সময় লাগে।&lt;/p&gt;

&lt;p&gt;এখন ফ্রন্টএন্ডে ইউজার পোস্ট ক্রিয়েট করার পর পরই যদি হোম পেজে গিয়ে সব পোস্ট ফেচ করতে চায়, তবে সিঙ্ক হতে সময় লাগার কারণে পুরানো ডাটা বা স্টেল ডাটা চলে আসতে পারে, তাই না?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;প্রশ্ন হলো:&lt;/strong&gt; রিয়েল-টাইমে লেটেস্ট ডাটা পাওয়ার জন্য এবং রিয়েল-টাইমে সব ইউজারের হোম পেজে সেই পোস্ট দেখানোর জন্য ফ্রন্টএন্ডে কীভাবে হ্যান্ডেল করবেন? আপনার সলিউশন কী—WebSocket নাকি অন্য কিছু?&lt;/p&gt;




&lt;h3&gt;
  
  
  সলিউশন:
&lt;/h3&gt;

&lt;p&gt;এই সিনারিওতে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long Polling:&lt;/strong&gt; বিবেচনা করা যাবে না, কারণ ডাটা একদম রিয়েল-টাইমে দেখাতে হবে।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short Polling:&lt;/strong&gt; অযথা একের পর এক অনর্থক API কল করে সার্ভারে লোড বাড়াবে।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebSocket:&lt;/strong&gt; এখানে Overkill । কারণ WebSocket Bidirectional যোগাযোগের জন্য ব্যবহৃত হয়। কিন্তু আমাদের সিনারিওতে ফ্রন্টএন্ডের কাজ শুধু সার্ভার থেকে রিয়েল-টাইমে ডাটা রিসিভ করা, ক্লায়েন্ট থেকে ব্যাকগ্রাউন্ডে কিছু পাঠানোর দরকার নেই।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-Sent Events (SSE):&lt;/strong&gt; এটাই হলো সবচেয়ে সেরা অপশন! এই মেথডে সার্ভার প্রয়োজন অনুযায়ী রিয়েল-টাইমে ফ্রন্টএন্ডে ডাটা পুশ করবে আর ফ্রন্টএন্ড শুধু ডাটা রিসিভ করে স্ক্রিনে দেখাবে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;যেহেতু রিড ও রাইটের জন্য দুটো আলাদা সার্ভিস রয়েছে, ফ্রন্টএন্ডে কখন ডাটা পাঠাব তা নিয়ে আমাদের সামনে দুটো অপশন থাকে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;অপশন ১:&lt;/strong&gt; write database-এ ডাটা ইনসার্ট হওয়ার সাথে সাথেই SSE-এর মাধ্যমে ফ্রন্টএন্ডে ডাটা পুশ করে দেওয়া।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;অপশন ২:&lt;/strong&gt; write database-এ ডাটা sync হওয়া পর্যন্ত অপেক্ষা করা, তারপর ফ্রন্টএন্ডে ডাটা পাঠানো।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;দুটো অপশনেরই জটিলতা ও কাজের ধরণ আলাদা। যেমন, অপশন ১-এ sync হওয়ার আগ পর্যন্ত সাময়িক কিছু সময়ের জন্য Inconsistency থাকতে পারে। তবে উপরের অপশনগুলোর মধ্যে &lt;strong&gt;SSE-ই সবচেয়ে কার্যকর সলিউশন&lt;/strong&gt;।&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(বি: দ্র: আমরা চাইলে Optimistic Way-তেও ডাটা পাঠাতে পারি, তবে সেক্ষেত্রে একটা Rollback Mechanism রাখতে হবে।)&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;Real-time-এর জন্য WebSocket বা SSE mandatory কিছু না। কোনটা use করতে হবে সেটা totally depend করবে আপনার application কী চাচ্ছে। Requirement-এর ওপর depend করেই decision নিতে হবে। এমনও case আছে যেখানে Short Polling-টাই best solution। For example, Log Aggregations করার ক্ষেত্রে। আপনি ২৪ ঘণ্টার interval দিয়ে log aggregate করতে পারেন। ওই situation-এ Short Polling সেরা perform করবে। তাই আপনার requirement কী সেটা আগে ঠিক করুন, তারপর decision নিন।&lt;/p&gt;

&lt;p&gt;আপনার প্রজেক্টে কোনটা ব্যবহার করেছেন? কোনো Challenge ছিল? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>programming</category>
      <category>web</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Day 17 — Message Broker — RabbitMQ vs Kafka</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Wed, 23 Sep 2026 04:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-17-message-broker-rabbitmq-vs-kafka-a4d</link>
      <guid>https://dev.to/mislam-dev/day-17-message-broker-rabbitmq-vs-kafka-a4d</guid>
      <description>&lt;p&gt;মনে করুন, একটি ই-কমার্স অ্যাপ্লিকেশন। কোনো ইউজার যখন একটি অর্ডার প্লেস করে, তখন ব্যাকএন্ডে একগুচ্ছ কাজ সম্পন্ন করতে হয়:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;কাস্টমারকে অর্ডার কনফার্মেশন ইমেইল পাঠাতে হবে।&lt;/li&gt;
&lt;li&gt;কনফার্মেশন SMS পাঠাতে হবে।&lt;/li&gt;
&lt;li&gt;ইনভেন্টরি বা স্টক আপডেট করতে হবে।&lt;/li&gt;
&lt;li&gt;অ্যানালিটিক্স ডাটা আপডেট করতে হবে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এই সবগুলো কাজ যদি অর্ডার হিট হওয়ার সাথে সাথেই সিঙ্ক্রোনাসলি (Synchronously) করতে চাই, তবে বেশ কিছু বড় সমস্যার মুখোমুখি হতে হবে:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;রেসপন্স টাইম অনেক বেশি বেড়ে যাবে এবং ইউজারকে স্ক্রিনে ওয়েট করে বসে থাকতে হবে।&lt;/li&gt;
&lt;li&gt;৩র্ড পার্টি ইমেইল বা SMS সার্ভিস ডাউন থাকলে পুরো অর্ডারটিই ফেল (Fail) মারবে।&lt;/li&gt;
&lt;li&gt;ডাটাবেসের মধ্যে ইনকনসিস্টেন্সি (Inconsistency) তৈরি হতে পারে।&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;এখন নিজেকে একটা প্রশ্ন করুন—ইউজার যখন পে পেজের "Confirm Order" বাটনে ক্লিক করে, তখন কি সে সাথে সাথে ইমেইল পাওয়া পর্যন্ত অপেক্ষা করতে চায়? নাকি ১ সেকেন্ডের মধ্যে "Order Successful" মেসেজ স্ক্রিনে দেখতে চায়?&lt;/p&gt;

&lt;p&gt;অবশ্যই ইউজার সাথে সাথে রেসপন্স দেখতে চায়! ইমেইল বা SMS ১ মিনিট পরে গেলেও কাস্টমারের কোনো সমস্যা নেই।&lt;/p&gt;

&lt;p&gt;এই যে ব্যাকগ্রাউন্ডে ভারী কাজগুলোকে সরিয়ে দিয়ে ইউজারকে দ্রুত রেসপন্স দেওয়া—এই সমস্যার সবচেয়ে চমৎকার সমাধান হলো &lt;strong&gt;Message Broker&lt;/strong&gt;।&lt;/p&gt;




&lt;h3&gt;
  
  
  Message Broker কী? 📬
&lt;/h3&gt;

&lt;p&gt;Message Broker ব্যাপারটিকে একটি পোস্ট অফিসের সাথে তুলনা করা যেতে পারে। &lt;/p&gt;

&lt;p&gt;আগে দূরে কোনো চিঠি বা বার্তা পৌঁছাতে পোস্ট অফিস ব্যবহার করা হতো। আপনি পোস্ট বক্সে চিঠি ফেলে দিয়ে চলে আসতেন এবং নিজের অন্যান্য কাজ শুরু করে দিতেন—চিঠি গন্তব্যে পৌঁছানো পর্যন্ত আপনি পোস্ট অফিসে দাঁড়িয়ে থাকতেন না!&lt;/p&gt;

&lt;p&gt;Message Broker ঠিক একই ধারণায় কাজ করে। মূল অ্যাপ্লিকেশন সার্ভিসটি মেসেজ ব্রোকারের কাছে একটি মেসেজ (বা ইভেন্ট) পুশ করে দিয়ে সাথে সাথে ইউজারকে রেসপন্স জানিয়ে দেয়। পরবর্তীতে ব্যাকগ্রাউন্ডের অন্যান্য Consumer সার্ভিসগুলো সেই মেসেজটি রিসিভ করে আস্তেধীরে প্রসেস করতে থাকে।&lt;/p&gt;

&lt;p&gt;বর্তমানে ব্যাকএন্ড ইঞ্জিনিয়ারিংয়ে দুটি মেসেজ ব্রোকার সবচেয়ে বেশি ব্যবহৃত হয়: &lt;strong&gt;RabbitMQ&lt;/strong&gt; এবং &lt;strong&gt;Apache Kafka&lt;/strong&gt;।&lt;/p&gt;




&lt;h3&gt;
  
  
  RabbitMQ: Smart Broker, Dumb Consumer 🐇
&lt;/h3&gt;

&lt;p&gt;RabbitMQ হলো একটি ঐতিহ্যবাহী ও বহুল ব্যবহৃত Message Queue সিস্টেম। এটি মূলত &lt;strong&gt;AMQP (Advanced Message Queuing Protocol)&lt;/strong&gt; স্ট্যান্ডার্ড অনুসরণ করে।&lt;/p&gt;

&lt;p&gt;এর মেকানিজম বেশ সহজ—এটি &lt;strong&gt;Push-based Model&lt;/strong&gt; মেনে চলে। প্রডিউসার মেসেজ পাঠালে ব্রোকার নিজে থেকে কনজিউমারের কাছে মেসেজ পুশ করে। কনজিউমার কাজ শেষে Acknowledgment (ACK) পাঠালে ব্রোকার কিউ থেকে মেসেজটি চিরতরে মুছে ফেলে।&lt;/p&gt;

&lt;h4&gt;
  
  
  💡 কখন RabbitMQ ব্যবহার করবেন?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Task Queue &amp;amp; Background Jobs:&lt;/strong&gt; ইমেইল পাঠানো, ছবি/ভিডিও প্রসেসিং, PDF রিপোর্ট জেনারেট করার মতো কাজের জন্য।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Message Routing:&lt;/strong&gt; নির্দিষ্ট শর্তে মেসেজ পাঠাতে চাইলে (যেমন: "শুধু VIP কাস্টমারদের প্রাইওরিটি ইমেইল কিউতে পাঠাও")।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guaranteed Delivery:&lt;/strong&gt; প্রতিটি মেসেজ যেন মিস না হয় এবং নিখুঁতভাবে অন্তত একবার প্রসেস হয়ে মুছে যায়।&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Apache Kafka: Dumb Broker, Smart Consumer 🚂
&lt;/h3&gt;

&lt;p&gt;Apache Kafka কিন্তু সাধারণ Message Queue নয়—এটি একটি &lt;strong&gt;Distributed Event Streaming Platform&lt;/strong&gt;। &lt;/p&gt;

&lt;p&gt;ক্যাফকা মেসেজকে মুছে ফেলার বদলে ডিস্কে একটি &lt;strong&gt;Append-only Commit Log&lt;/strong&gt; হিসেবে সংরক্ষণ করে রাখে। প্রডিউসার ইভেন্ট রাইট করে যায়, আর কনজিউমার নিজের অফসেট (Offset) ট্র্যাক করে নিজের গতিতে ডাটা রিড (Pull Model) করতে থাকে। মেসেজ পড়ার পরও ক্যাফকা থেকে ডাটা মুছে যায় না (নির্ধারিত Retention সময় পর্যন্ত সংরক্ষিত থাকে)।&lt;/p&gt;

&lt;h4&gt;
  
  
  💡 কখন Apache Kafka ব্যবহার করবেন?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Volume Real-time Event Streaming:&lt;/strong&gt; প্রতি সেকেন্ডে লাখ লাখ ইভেন্ট বা লগ প্রসেস করতে হলে (যেমন: উবার রাইড ট্র্যাকিং, ক্রেডিট কার্ড ফ্রড ডিটেকশন)।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Replayability:&lt;/strong&gt; পুরানো ইভেন্ট আবার নতুন করে প্রসেস বা রিঅ্যালাইজ করার প্রয়োজন হলে।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Independent Consumers:&lt;/strong&gt; একই ইভেন্ট স্ট্রিম থেকে আলাদা আলাদা মাইক্রোসার্ভিস (Analytics, Fraud Detection, Notification) স্বাধীনভাবে ডাটা রিড করতে চাইলে।&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  RabbitMQ vs Apache Kafka: মুখোমুখি তুলনা ⚖️
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;বৈশিষ্ট্য&lt;/th&gt;
&lt;th&gt;RabbitMQ 🐇&lt;/th&gt;
&lt;th&gt;Apache Kafka 🚂&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;আর্কিটেকচার টাইপ&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Traditional Message Queue&lt;/td&gt;
&lt;td&gt;Distributed Event Streaming Log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ডাটা মডেল&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Queue (Message প্রসেস হলে মুছে যায়)&lt;/td&gt;
&lt;td&gt;Log Stream (মেসেজ ডিস্কে সেভ থাকে)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;মেসেজ ডেলিভারি&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Push Model (Broker → Consumer)&lt;/td&gt;
&lt;td&gt;Pull Model (Consumer ← Broker)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;হাজার হাজার মেসেজ/সেকেন্ড&lt;/td&gt;
&lt;td&gt;লাখ লাখ মেসেজ/সেকেন্ড&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Message Routing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;অত্যন্ত শক্তিশালী (Exchange, Routing Keys)&lt;/td&gt;
&lt;td&gt;সিম্পল (Topic &amp;amp; Partition ভিত্তিক)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replayability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;সাপোর্ট করে না (ACK পেলে ডিলিট)&lt;/td&gt;
&lt;td&gt;চমৎকার (Offset পিছিয়ে আবার পড়া যায়)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Real-World Example: অর্ডার প্রসেসিং ফ্লো
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;RabbitMQ ফ্লো:&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ইউজার অর্ডার দিল → Order Service মেসেজ পাঠাল &lt;strong&gt;RabbitMQ&lt;/strong&gt;-তে → ইউজারকে সাথে সাথে Success রেসপন্স দেওয়া হলো।&lt;/li&gt;
&lt;li&gt;ব্যাকগ্রাউন্ডে &lt;strong&gt;Email Worker&lt;/strong&gt; বা &lt;strong&gt;SMS Worker&lt;/strong&gt; মেসেজ পিক করল → ইমেইল পাঠিয়ে দেওয়ার পর RabbitMQ মেসেজটি ডিলিট করে দিল।&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Kafka ফ্লো:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ইউজার রাইড বুক করল → Ride Service &lt;strong&gt;Kafka Topic (&lt;code&gt;ride-events&lt;/code&gt;)&lt;/strong&gt;-এ ইভেন্ট রাইট করল।&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location Tracker Service&lt;/strong&gt;, &lt;strong&gt;Billing Service&lt;/strong&gt;, এবং &lt;strong&gt;Analytics Engine&lt;/strong&gt;—তিনটি স্বাধীন সার্ভিস একই সাথে ক্যাফকা টপিক থেকে প্যারালালি ডাটা রিড করে নিজেদের কাজ সম্পন্ন করল।&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  বটম লাইন
&lt;/h3&gt;

&lt;p&gt;RabbitMQ এবং Kafka দুটিই অসাধারণ প্রযুক্তি—তবে তারা ভিন্ন সমস্যার সমাধান করে। যদি আপনার নির্দিষ্ট কাজ প্রসেস করার জন্য নির্ভরযোগ্য Task Queue দরকার হয় যেখানে মেসেজ প্রসেস হয়ে মুছে গেলেই চলে, তবে &lt;strong&gt;RabbitMQ&lt;/strong&gt; বেছে নিন। আর যদি আপনার প্রতি সেকেন্ডে বিশাল আকারের ইভেন্ট স্ট্রিম প্রসেস ও অ্যানালিটিক্সের প্রয়োজন হয়, তবে &lt;strong&gt;Apache Kafka&lt;/strong&gt; হলো সেরা পছন্দ।&lt;/p&gt;

&lt;p&gt;আপনার প্রজেক্টে ব্যাকগ্রাউন্ড টাস্ক বা ইভেন্ট প্রসেস করার জন্য কোন মেসেজ ব্রোকার ব্যবহার করছেন? কমেন্টে জানান! 👇&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
