2.4
HTTP Caching: Cache-Control, ETag ও Validation
Freshness, revalidation, Vary, shared বনাম private cache, আর নিরাপদে পুরোনো content দেখানো।
38 মিনিট পড়া + Animation
টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।
এই Lesson শেষে তুমি পারবে
- বোঝাতে, HTTP Caching কেন তোমার হাতে থাকা সবচেয়ে সস্তা Performance আর Scaling-এর হাতিয়ার, আর একটা Fresh Hit, একটা 304 আর একটা পুরো 200-এর দাম আলাদা করে বলতে।
- Private Cache (Browser) আর Shared Cache (Proxy, Gateway, CDN) আলাদা করতে, আর কোনটা কোন Response রাখতে পারে তা বলতে।
max-age,s-maxage,Expires,Ageআর আন্দাজের (Heuristic) Freshness দেখে হিসাব করতে, জমা Response-টা এখনো Fresh কি না।- ঠিক
Cache-ControlDirective বাছতে, আরno-cache,no-store,private,public,must-revalidateআরimmutableঠিক কোথায় আলাদা, তা বোঝাতে। - ETag (Strong আর Weak) আর
Last-Modifiedদিয়ে আবার যাচাই (Revalidate) করতে, আর একটা 304-এর প্রতিটা Header পড়তে। Varyদিয়ে Cache Key সাজাতে,Vary: User-Agent-এর ফাঁদে না পড়ে; আরstale-while-revalidateওstale-if-errorদিয়ে ইচ্ছে করে পুরনো (Stale) Content দেখাতে।- Hash-ওয়ালা File-এর নাম দিয়ে এমন Deploy করতে, যাতে কোনো ব্যবহারকারী পুরনো JavaScript-এ আটকে না থাকে।
- HTML, Static Asset, Public API আর ব্যক্তিগত Data-র জন্য Caching Policy লিখতে, লগইন করা ব্যবহারকারীর Response নিরাপদে Cache করতে, আর API-তে ETag আর
If-Matchদিয়ে হারানো Update ঠেকাতে।
#এই Lesson কোথায় বসে
Lesson ১.১-এ Cache-Control, ETag আর 304 Status এক লাইনে করে এসেছিল। Lesson ১.৮-এ DNS-এ একই ধারণা দেখেছি: TTL ঠিক করে একটা উত্তর কতক্ষণ আবার ব্যবহার করা যাবে, আর “Propagation” আসলে Cache-এর মেয়াদ ফুরোনো। Lesson ১.১২ আর Lesson ১.১৩-এ দেখেছি Proxy আর Nginx কীভাবে Response Cache করে, আর Fingerprint-ওয়ালা File-এ public, immutable Header। কোন Method Cache করা যায় তা আছে Lesson ২.২-এ, আর Header ও Compression কীভাবে কাজ করে তা Lesson ২.৩-এ।
এই Lesson-এ পুরো Protocol-টা: তোমার Browser থেকে CDN পর্যন্ত যেকোনো HTTP Cache কীভাবে ঠিক করে একটা Response জমা রাখা যাবে কি না, কতক্ষণ আবার ব্যবহার করা যাবে, সস্তায় কীভাবে আবার যাচাই করবে, আর Header কীভাবে দিলে ব্যবহারকারী গতি পাবে অথচ কখনো ভুল Data দেখবে না। CDN-এর ভেতরটা কেমন, Redis দিয়ে Cache-aside, Eviction Policy আর Stampede, এগুলো Chapter 23 আর 24-এর বিষয়; এখানে আমরা থাকব HTTP নিজে যা বলে, তার মধ্যে।
#HTTP Caching কেন
HTTP Caching মানে একটা Response-এর কপি ব্যবহারকারীর কাছাকাছি রেখে দেওয়া, Browser-এ বা কোনো Proxy বা CDN-এ, আর পরের Request-এ Origin Server-কে আবার না জিজ্ঞেস করে সেই কপিটাই ব্যবহার করা। তিন রকম ফল হতে পারে, আর তিনটার দাম একদম আলাদা:
| ফল | কী ঘটে | Network-এর খরচ | Origin-এর কাজ |
|---|---|---|---|
| Fresh Hit | জমা কপি এখনো Fresh, তাই সরাসরি ব্যবহার | কিছুই না: DNS নেই, Connection নেই, ০ Byte | কিছুই না; Origin জানতেও পারে না |
| আবার যাচাই (304) | কপি Stale, তাই Cache জিজ্ঞেস করে “বদলেছে কি?” আর উত্তর আসে, না | এক Round Trip, কয়েকশো Byte | সস্তা একটা যাচাই |
| পুরো আনা (200) | কপি নেই, বা Resource বদলে গেছে | এক বা একাধিক Round Trip আর পুরো Body | পুরো কাজ |
ঢাকার একটা 4G ফোন থেকে Singapore-এর Server পর্যন্ত প্রতিটা Round Trip-এ ধরো ১৫০ ms লাগে। একটা Page-এর ৫০টা File-এর ৪০টা যদি Cache থেকে আসে, তাহলে ওই ৪০টা Request আর হয়ই না। ব্যবসার দিক থেকে লাভ দুই দিকে: ব্যবহারকারী দ্রুত Page পায়, আর প্রতিটা Hit এমন একটা Request, যা তোমার Server বা Bandwidth-এর বিলে কখনো ওঠে না। CDN যদি ৯৫% Request-এর উত্তর দেয়, Origin সামলায় মাত্র ৫%; Hit Ratio ৯০% থেকে ৯৫% করলে Origin-এর চাপ অর্ধেক হয়ে যায়।
প্রতিটা Cache যে সিদ্ধান্ত নেয়, নোটে সেটাই আঁকা আছে:
[ Browser / client cache ]
|
(Is the copy fresh?)
/ \
(Yes) (No: stale)
/ \
[ Use it: memory / disk ] [ Conditional request ]
(If-None-Match: ETag, or
If-Modified-Since: date)
|
(Server validation)
/ \
(304 Not Modified) (200 OK + new body)
reuse the stored body replace the copy
Cache-এ রাখা একটা File-এর জীবন: জমা, Fresh, Stale, আবার যাচাই
একটা Logo, একটা Browser, একটা Origin। প্রথম ভিজিট, Network ছাড়াই আবার ব্যবহার, মেয়াদ ফুরোনো আর সস্তা 304 যাচাই, আর যখন File সত্যিই বদলেছে বা Server কোনো নিয়মই দেয়নি, সব ধাপে ধাপে দেখো।
পরিস্থিতি
এখনো কিছু জমা নেই, তাই পুরো File আসে, আর Response বলে দেয় কতক্ষণ আবার ব্যবহার করা যাবে।
Page-এর প্রতিটা Request আগে Browser-এর HTTP Cache হয়ে যায়। Cache তার Key খোঁজে: Method আর পুরো URL।
#Cache কোথায় থাকে: Private আর Shared
HTTP Standard (RFC 9111) দুই রকম Cache চেনে, আর প্রায় প্রতিটা নিয়ম নির্ভর করে তুমি কোনটার কথা বলছ তার ওপর।
| Cache | ধরন | কাকে সেবা দেয় | সাধারণত কী থাকে |
|---|---|---|---|
| Browser-এর HTTP Cache (Memory আর Disk) | Private | একজন ব্যবহারকারী, একটা Browser Profile | Cache করা যায় এমন সব: HTML, CSS, JavaScript, ছবি, Font, API Response |
| Service Worker Cache | Private, Code দিয়ে চালানো | একজন ব্যবহারকারী, একটা Site | Site-এর নিজের Script যা ঠিক করে (Offline App) |
| অফিস বা ISP-এর Forward Proxy | Shared | পেছনের সবাই | আজকাল সামান্যই: TLS ভেঙে না দেখলে HTTPS-এর ভেতরে দেখতে পারে না |
| Reverse Proxy / API Gateway (Nginx, Varnish) | Shared | তোমার Site-এর সব ব্যবহারকারী | App Server-এর সামনে Public Page আর API Response |
| CDN Edge (Cloudflare, CloudFront, Fastly, Akamai) | Shared | ওই Edge-এর কাছের সবাই | Static Asset, Public Page, Video-র টুকরো, Public API Response |
Private Cache একজন মানুষের জন্য বানানো Response রাখতে পারে, যেমন তোমার Profile Page। Shared Cache কখনোই তা পারবে না, কারণ তার পরের জন তোমার Page পেয়ে যাবে। এই একটা নিয়মই ব্যাখ্যা করে private, public, s-maxage আর Caching-এর বেশিরভাগ নিরাপত্তা-Bug।
Browser-এর Cache নিয়ে আরও দুটো কথা:
- এটা Memory আর Disk দুটোই ব্যবহার করে। ছোট, সদ্য ব্যবহার করা Response চলতি Session-এর জন্য Memory-তে থাকে; DevTools এগুলোকে লেখে “(memory cache)” বা “(disk cache)”। নোট বলে File থাকে “ডিভাইসের Disk-এ”, সেটা অর্ধেক সত্যি।
- এটা ভাগ করা (Partitioned)। ২০২০–২০২১ থেকে Chrome, Firefox আর Safari Cache-এর Key-তে URL-এর সাথে Top-level Site-ও রাখে। ফলে
a.example-এ গিয়ে Cache হওয়া Fileb.example-এ আবার ব্যবহার হয় না। এতে কোনো Site Cache-এর সময় মেপে তোমার History আন্দাজ করতে পারে না; আর “Public CDN থেকে jQuery তো সবার Cache-এ আছেই”, এই কথাটা আর সত্যি না।
#কী কী Cache করা যায়
- Method: বাস্তবে শুধু
GETআরHEAD-এর Response Cache হয়।POST-এর Response আবার ব্যবহার করা যায় শুধু স্পষ্ট বলে দিলে, আর প্রায় কখনোই Cache হয় না (Safe আর Cacheable Method নিয়ে Lesson ২.২)। - Status Code: স্পষ্ট Freshness থাকলে যেকোনো Response রাখা যায়। না থাকলে রাখা যায় শুধু সেই Code-গুলো, যাদের Standard বলে আন্দাজে Cache করা যায় (Heuristically Cacheable): 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414 আর 501। তাই কোনো Header ছাড়া একটা 404-ও Cache হতে পারে, আর Browser 301 খুব শক্ত করে মনে রাখে।
- ডিফল্ট Key হলো Method আর পুরো URL (Scheme, Host, Path আর Query String)। শুধু একটা Tracking Parameter-এ আলাদা দুটো URL মানে দুটো আলাদা Entry।
#Freshness: একটা কপি কতক্ষণ আবার ব্যবহার করা যায়
জমা Response Fresh থাকে যতক্ষণ তার বয়স (Age) তার Freshness-এর মেয়াদের চেয়ে কম, তারপর সেটা Stale। Fresh কপি কাউকে না জিজ্ঞেস করেই ব্যবহার হয়; Stale কপি সাধারণত আগে আবার যাচাই হয়। Stale মানে ভুলও না, মুছে ফেলাও না: Cache সেটা রেখে দেয়, কারণ একটা সস্তা 304 তাকে আবার কাজের করে তুলতে পারে।
#max-age আর Expires
Cache-Control: max-age=3600
Expires: Mon, 02 Nov 2026 12:00:00 GMT
max-age=Nমেয়াদ দেয় সেকেন্ডে, Response তৈরির মুহূর্ত থেকে গুনে।max-age=3600মানে এক ঘণ্টা;max-age=31536000(নোটের উদাহরণ) মানে এক বছর, প্রচলিত “চিরকাল”।Expiresদেয় একটা নির্দিষ্ট তারিখ আর সময়, সবসময় GMT-তে, আর বারের নামও ঠিক হতে হয়। এটা HTTP/1.0-র পদ্ধতি, আর Server আর Client-এর ঘড়ি মিলতে হয়।Expires: 0-এর মতো অচল মান মানে “মেয়াদ আগেই শেষ”।- দুটোই থাকলে সবসময়
max-ageজেতে, সব Cache-এ। (নোট বলে “সাধারণত”; Standard বলে সবসময়।)
দুটোই Freshness বোঝায়, কপি কতদিন রাখা হবে তা না। জায়গা লাগলে Cache Fresh Entry-ও আগে মুছে দিতে পারে, আবার Stale Entry অনেকদিন রেখে দিতে পারে, পরে আবার যাচাইয়ের আশায়।
#s-maxage: Shared Cache-এর আলাদা মেয়াদ
s-maxage=N খাটে শুধু Shared Cache-এ, আর সেখানে max-age (আর Expires)-কে ছাপিয়ে যায়। Browser এটা উপেক্ষা করে। চেনা ধরনটা হলো Browser-এ ছোট মেয়াদ, CDN-এ লম্বা:
Cache-Control: max-age=60, s-maxage=600
কেন? কিছু বদলালে CDN কয়েক সেকেন্ডে Purge করা যায়, কিন্তু ব্যবহারকারীর Browser-এ তুমি কখনো হাত দিতে পারবে না। তাই যে কপি মুছতে পারো, লম্বা মেয়াদ তারই। অনেক CDN এর জন্য নিজস্ব Header-ও নেয়, যেমন CDN-Cache-Control (২০২২ থেকে Standard) বা Surrogate-Control, যেগুলো তারা পড়ে আর সরিয়ে দেয়; Chapter 24-এ এগুলো আসবে।
#Age: অন্য Cache-এ আগেই কাটানো সময়
Shared Cache জমা Response দেওয়ার সময় একটা Age Header যোগ করে: Origin Response তৈরি বা শেষবার যাচাই করার পর কত সেকেন্ড গেছে। পরের Cache সেই সময়টাও গোনে:
বর্তমান বয়স = এই Cache-এ কপিটা যতক্ষণ আছে + যে Age নিয়ে এসেছিল
তাই max-age=60-ওয়ালা একটা Response CDN থেকে Age: 40 নিয়ে এলে Browser-এ তার Freshness বাকি থাকে মাত্র ২০ সেকেন্ড। Age: 300 নিয়ে এলে পৌঁছানোর সময়েই সেটা Stale, আর Browser প্রতিবার ব্যবহারের আগে যাচাই করবে: ছোট max-age আর লম্বা s-maxage একসাথে দেওয়ার এক অবাক করা খরচ।
#আন্দাজের Freshness: Server যখন কিছুই বলে না
Response-এ max-age, s-maxage বা Expires না থাকলে, কিন্তু Last-Modified তারিখ থাকলে, Standard Cache-কে একটা মেয়াদ আন্দাজ করার অনুমতি দেয়। প্রচলিত নিয়ম হলো শেষ পরিবর্তনের পর থেকে যত সময় গেছে তার ১০%: ১০ দিন আগে শেষ বদলানো File প্রায় এক দিনের জন্য Fresh ধরা হয়। এভাবেই একটা ভুলে যাওয়া Header হয়ে যায় “Fix-এর এক দিন পরেও ব্যবহারকারী পুরনো File দেখছে”। সবসময় স্পষ্ট একটা Cache-Control পাঠাও, শুধু no-cache হলেও।
#Cache-Control Directive
Cache-Control হলো কমা দিয়ে আলাদা করা Directive-এর তালিকা, বেশিরভাগ Response-এ পাঠানো হয়:
| Directive | মানে | সাধারণ ব্যবহার |
|---|---|---|
max-age=N | যেকোনো Cache-এ N সেকেন্ড Fresh | Cache করা যায় এমন বেশিরভাগ Response |
s-maxage=N | Shared Cache-এ N সেকেন্ড Fresh; সেখানে max-age-কে ছাপিয়ে যায় | Browser-এর চেয়ে লম্বা CDN মেয়াদ |
no-cache | রাখা যাবে, কিন্তু প্রতিবার ব্যবহারের আগে Origin-এর সাথে যাচাই করতে হবে | HTML Page, যে Data সবসময় হালনাগাদ থাকতে হবে |
no-store | Private বা Shared, কোনো Cache-এ রাখা যাবে না | Bank Statement, এককালীন Token, স্বাস্থ্যের রেকর্ড |
private | শুধু Private Cache (Browser) রাখতে পারবে | একজন ব্যবহারকারীর Page আর API Response |
public | এমন অবস্থাতেও Shared Cache রাখতে পারবে, যেখানে সাধারণত পারে না (Authorization-ওয়ালা Request, স্পষ্ট মেয়াদ নেই) | কদাচিৎ লাগে; নিচে দেখো |
must-revalidate | Stale হলে সফল যাচাই ছাড়া কখনো ব্যবহার নয়; Origin-এ পৌঁছানো না গেলে Error (504) | যেখানে Stale-এর চেয়ে Error ভালো |
proxy-revalidate | must-revalidate-এর মতোই, শুধু Shared Cache-এর জন্য | বিরল |
immutable | Fresh থাকা অবস্থায় এই Body কখনো বদলাবে না, তাই Reload-এও যাচাই কোরো না | Hash-ওয়ালা Static File |
stale-while-revalidate=N | মেয়াদ শেষে আরও N সেকেন্ড Stale কপি দেওয়া যাবে, পেছনে Refresh চলতে চলতে | যেখানে কয়েক সেকেন্ড পুরনো হলে সমস্যা নেই |
stale-if-error=N | আবার যাচাই ব্যর্থ হলে (5xx বা উত্তরই নেই) N সেকেন্ড Stale কপি দেওয়া যাবে | Origin বিভ্রাটের সময় Site চালু রাখা |
no-transform | Proxy Body বদলাতে পারবে না (ছবি আবার Compress, Minify) | যে Media-কে Byte-এ Byte-এ এক থাকতে হবে |
Request-এও Cache-Control থাকতে পারে। Hard Reload পুরো Download জোর করাতে Cache-Control: no-cache পাঠায়; max-age=0 আবার যাচাই চায়; only-if-cached চায় জমা কপি, নয়তো কিছুই না। পুরনো Pragma: no-cache Header HTTP/1.0-এর অবশেষ, বর্তমান Standard একে বাতিল করেছে; তবু পুরনোদের সাথে মিল রাখতে Browser এখনো Cache-Control-এর পাশাপাশি এটা পাঠায়।
Cache-Control Directive: Private বনাম Shared Cache
Browser হলো Private Cache (একজন ব্যবহারকারী)। CDN হলো Shared Cache (সবার)। প্রতিটা Directive ঠিক করে কে Response জমা রাখতে পারবে, কতক্ষণ, আর আগে জিজ্ঞেস করতে হবে কি না।
পরিস্থিতি
সব জায়গায় জমা থাকে, কিন্তু প্রতিবার ব্যবহারের আগে Origin-এর সাথে যাচাই করতে হয়।
নামটা বিভ্রান্তিকর: no-cache Cache করা নিষেধ করে না। দুটো Cache-ই Page জমা রাখে, কিন্তু Origin-কে জিজ্ঞেস না করে কেউই আবার ব্যবহার করতে পারে না। যে HTML সবসময় হালনাগাদ থাকতে হবে, তার জন্য এটাই চলে।
নিজেকে যাচাই করোপ্রশ্ন
একটা HTML Page সবসময় হালনাগাদ থাকতে হবে, কিন্তু কিছু না বদলালে আবার Download এড়াতে চাও। কোন Header মানায়?
#Validation: ETag আর Last-Modified
জমা Response Stale হলে Cache সেটা ফেলে দেয় না। সে একটা Conditional Request পাঠায়, যার মানে “আমার কাছে এটা আছে; বদলালে তবেই নতুন Body পাঠাও”। এটা সম্ভব করতে আসল Response-এ একটা Validator থাকতে হয়।
#ETag আর If-None-Match
ETag (Entity Tag) হলো একটা Resource-এর একটা Version-এর জন্য একটা অস্বচ্ছ (Opaque) নাম:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
ETag: "hash_v123"
পরে Cache জিজ্ঞেস করে:
GET /logo.png HTTP/1.1
If-None-Match: "hash_v123"
বর্তমান ETag এখনো "hash_v123" হলে Server উত্তর দেয় 304 Not Modified, Header সহ কিন্তু Body ছাড়া। না হলে নতুন Body আর নতুন ETag সহ 200 OK। যেটাই হোক, খরচ মাত্র এক Round Trip।
ভালো ETag কেমন হয়:
- এমন যেকোনো String, যা Body বদলালেই বদলায়। নোট যেমন বলে, Content-এর Hash খুব চলে, কিন্তু Database Row-এর Version বা Update-এর গুনতি (
"v42") একই রকম কাজ করে, আর বড় Response Hash করার চেয়ে সস্তা। - প্রতিটা Server-এ একই। Load Balancer-এর পেছনে তিনটা Server-কে একই File-এর জন্য একই ETag বানাতে হবে। পুরনো Apache-র ডিফল্ট File-এর Inode নম্বর মিশিয়ে দিত, যা প্রতিটা মেশিনে আলাদা; ফলে অন্য Server-এ পড়া প্রতিটা Request 304-এর বদলে পুরো 200 পেত।
- Strong না Weak। সাধারণ
"abc"হলো Strong Validator: Byte-এ Byte-এ এক।W/"abc"হলো Weak: “অর্থে এক”, যেমন একই Page, শুধু একটা Comment-এ সময় আলাদা।If-None-MatchWeak তুলনা করে, তাই Caching-এ দুটোই চলে; কিন্তু Range Request আরIf-Match-এর জন্য Strong ETag লাগে। Nginx চলতে চলতে Compress করলে Strong ETag-কে Weak বানিয়ে দেয়, কারণ Byte-গুলো আর এক থাকে না।
#Last-Modified আর If-Modified-Since
পুরনো, সময়ভিত্তিক Validator:
Last-Modified: Wed, 21 Oct 2026 07:28:00 GMT
...
If-Modified-Since: Wed, 21 Oct 2026 07:28:00 GMT
ওই মুহূর্তের পর Resource না বদলালে Server 304 দেয়। এর জন্য বাড়তি কিছু রাখতে হয় না, কিন্তু এর মাপ এক সেকেন্ড পর্যন্ত: একই সেকেন্ডে দুবার বদলানো, Deploy-এ File-এর পুরনো সময় ফিরে আসা, বা Server-গুলোতে File-এর সময় আলাদা হওয়া, সবকটাতেই এটা ভুল বলে। Request-এ If-None-Match আর If-Modified-Since দুটোই থাকলে Server-কে ETag-টাই দেখতে হবে। ETag পাঠাও; Last-Modified রাখো বিকল্প হিসেবে (আন্দাজের Freshness-এও এটা লাগে, আর Crawler-দের কাজে আসে)।
#একটা 304 আসলে কী বলে
304 মানে “তোমার কপি Fresh ছিল” না: Fresh কপি তো যাচাই-ই হতো না। মানে হলো “তোমার Stale কপিটা এখনো ঠিক আছে”। 304-এ Body নেই, কিন্তু Header থাকে (ETag, Cache-Control, Expires, Vary, Date), আর Cache সেগুলো দিয়ে জমা Header আপডেট করে আর Freshness-এর ঘড়ি নতুন করে চালু করে। এভাবেই File আবার না পাঠিয়েও Cache-এ থাকা File-এর মেয়াদ বদলানো যায়।
সব Conditional Header এক জায়গায়:
| Request Header | কার সাথে জোড়া | কী কাজে | শর্ত ব্যর্থ হলে |
|---|---|---|---|
If-None-Match: "e" | ETag | Cache আবার যাচাই (GET) | 304 Not Modified |
If-Modified-Since: date | Last-Modified | Cache আবার যাচাই (GET) | 304 Not Modified |
If-Match: "e" | ETag (Strong) | নিরাপদ Update (PUT, PATCH, DELETE) | 412 Precondition Failed |
If-Unmodified-Since: date | Last-Modified | নিরাপদ Update, পুরনো ধরন | 412 Precondition Failed |
If-Range: "e" | ETag বা তারিখ | File না বদলালে তবেই অর্ধেক Download আবার শুরু | 206 Range-এর বদলে পুরো 200 |
If-None-Match: * | — | কিছু না থাকলে তবেই তৈরি (PUT) | 412 Precondition Failed |
#Cache Key আর Vary
Cache প্রতিটা Response একটা Key-এর নিচে রাখে, ডিফল্টে Method আর পুরো URL। কিন্তু এক URL-এর একাধিক সঠিক উত্তর থাকতে পারে: Brotli-তে Compress করা আর না-করা app.js, ইংরেজি আর বাংলা Page। Response-এর Vary Header বলে দেয়, জমা Response আবার ব্যবহারের আগে Request-এর আর কোন কোন Header মিলতে হবে:
Vary: Accept-Encoding
এবার Cache প্রতিটা আলাদা Accept-Encoding মানের জন্য একটা করে Entry রাখে, আর প্রত্যেক Client-কে সেই Body দেয়, যা সে পড়তে পারে।
Vary: Accept-Encodingপ্রায় প্রতিটা Compressed Response-এর লাগে (gzip, Brotli আর zstd নিয়ে Lesson ২.৩)। এটা ভুলে গেলে Shared Cache এমন Client-কেও Brotli Byte দিয়ে দেয়, যে কখনো চায়ইনি। CDN এই Header-কে অল্প কয়েকটা মানে নামিয়ে আনে, যাতে অনেক Variant না হয়।Vary: User-Agentএকটা ফাঁদ। হাজার হাজার আলাদা User-Agent String আছে, তাই Cache হাজারটা ছোট্ট Entry-তে ভেঙে যায় আর Hit Ratio ধসে পড়ে। ফোনের জন্য আলাদা HTML দিতেই হলে CDN-কে User-Agent থেকে Device-এর ধরন বের করতে দাও (বাSec-CH-UA-MobileClient Hint ব্যবহার করো) আর তার ওপর Vary দাও; আরও ভালো, একটাই Responsive Page বানাও।Vary: CookieCache-কে প্রতিটা Cookie-মানের জন্য একটা কপি রাখায়, যা লগইন করা ব্যবহারকারীদের ক্ষেত্রে মানে প্রত্যেকের জন্য একটা কপি: সঠিক, কিন্তু Shared Cache-এ প্রায় অকেজো। এমন Response-কে বরংprivateদাও।Vary: Accept-Languageঠিক আছে, যদি CDN একে তোমার সমর্থিত ভাষাগুলোতে নামিয়ে আনে; না হলে প্রতিটা Browser-এর একটু আলাদা ভাষার তালিকা নতুন একটা Variant।Vary: *মানে “কখনো আবার ব্যবহার কোরো না”,no-storeলেখার একটা আনাড়ি উপায়।
বেশিরভাগ CDN সরাসরি Key সাজাতেও দেয়: Tracking Parameter (utm_*, fbclid) বাদ দেওয়া, Query String সাজানো, বা কোনো Header বা Cookie Key-তে যোগ করা। এগুলো CDN-এর Configuration, Chapter 24-এ শেখানো হবে; HTTP-র নিজের হাতিয়ার হলো Vary।
Cache Key আর Vary: এক URL, কয়েকটা জমা উত্তর
Cache প্রতিটা Response একটা Key-এর নিচে রাখে: ডিফল্টে Method আর URL। Vary বলে দেয় Request-এর আর কোন কোন Header মিলতে হবে। Stage-এর নিচে CDN-এর টেবিলটা খেয়াল করো।
পরিস্থিতি
একই File-এর Compressed আর Uncompressed কপি, ঠিকঠাক আলাদা রাখা।
User A-র Browser Brotli নিতে পারে। CDN-এর কাছে এখনো কিছু নেই, তাই Request সামনে পাঠায়।
#ইচ্ছে করে Stale দেখানো
দুটো Directive (RFC 5861) Cache-কে জেনেবুঝে Stale কপি ব্যবহার করতে দেয়, একটু Freshness-এর বদলে গতি বা সবসময় চালু থাকা কিনে নিতে:
Cache-Control: max-age=60, stale-while-revalidate=300, stale-if-error=86400
stale-while-revalidate=300: কপি Stale হওয়ার পর ৩০০ সেকেন্ড ধরে Cache সাথে সাথে Stale কপি দিয়ে উত্তর দিতে পারে, আর পেছনে সেটা Refresh করে। ব্যবহারকারীকে কখনো Origin-এর Render-এর সময় অপেক্ষা করতে হয় না; দামটা Cache একবার দেয়। Chromium Browser আর Firefox এটা মানে, বড় CDN-গুলোও।stale-if-error=86400: আবার যাচাই ব্যর্থ হলে (500, 502, 503 বা 504, বা উত্তরই নেই) Cache এক দিন পর্যন্ত Stale কপি দিয়ে যেতে পারে। Database বন্ধ থাকলেও তোমার Home Page চালু থাকে। Cloudflare, Fastly, CloudFront-এর মতো CDN এটা মানে; বেশিরভাগ Browser মানে না, তাই এটাকে Shared Cache-এর হাতিয়ার ধরো।must-revalidateউল্টোটা করে: Origin-এ পৌঁছানো না গেলেও Stale দেখাতে নিষেধ করে। এটা দাও যেখানে ভুল উত্তর Error-এর চেয়েও খারাপ (যে Stock-এর হিসাব দেখে Payment নেওয়া হয়, যে Feature Flag একটা বিপজ্জনক পথ বন্ধ রাখে)।
এমন Response-এর Age Header জানায় সেটা আসলে কত পুরনো। stale-while-revalidate Cache Stampede-কেও নরম করে, যেখানে একটা মেয়াদোত্তীর্ণ Key-এর জন্য অনেক Request একসাথে Origin-এ আছড়ে পড়ে; Lock আর Request Coalescing সহ পুরো আলোচনা Chapter 23-এ।
ইচ্ছে করে Stale দেখানো: stale-while-revalidate আর stale-if-error
Response: Cache-Control: max-age=60, stale-while-revalidate=300, stale-if-error=86400। ১ মিনিট Fresh, তারপর আরও ৫ মিনিট Refresh চলাকালীন ব্যবহারযোগ্য, আর Origin বিপদে থাকলে এক দিন পর্যন্ত ব্যবহারযোগ্য।
পরিস্থিতি
৯০ সেকেন্ড বয়সে কপিটা Stale, কিন্তু ৩০০ সেকেন্ডের জানালার ভেতরে: ব্যবহারকারী সাথে সাথে পায়, Refresh হয় পেছনে।
Cache-এ থাকা Home Page-এর বয়স ৯০ সেকেন্ড: Stale, কারণ max-age ৬০।
#Hash-ওয়ালা File-এর নাম দিয়ে Cache Busting
লম্বা মেয়াদ আর ঠিকঠাক Update যেন একে অপরের শত্রু: File এক বছর Cache করলে ব্যবহারকারী নতুন Version পায় না; এক মিনিট করলে লাভের বেশিরভাগই হারাও। উত্তর হলো, একই URL-এর নিচে কখনো File বদলাবে না:
১. Build Tool প্রতিটা Static File-এর নাম দেয় তার Content-এর Hash দিয়ে: app.a83f92.js, style.72bc1.css। এক লাইন বদলালেই নাম বদলে যায়।
২. এই File-গুলো যায় Cache-Control: public, max-age=31536000, immutable দিয়ে: এক বছর Cache, কখনো আবার যাচাই নয়, কারণ একটা নামের Content কখনো আলাদা হতে পারে না।
৩. HTML স্বল্পমেয়াদি: no-cache (ETag সহ), বা CDN-এ কয়েক সেকেন্ড থেকে কয়েক মিনিট, Deploy-এ Purge সহ। বদলায় শুধু HTML, আর সেটাই নতুন File-এর নাম দেখিয়ে দেয়।
৪. Deploy-এর পর Browser HTML আবার যাচাই করে, নতুন নাম দেখে, আর শুধু সত্যিই বদলানো File-গুলো আনে। না-বদলানো File নাম রাখে, Cache-এই থাকে।
৫. Deploy-এর পরও কয়েক দিন পুরনো File রেখে দাও। যাদের Tab খোলা, আর কোথাও এখনো Cache-এ থাকা HTML, তারা এখনো সেগুলো চায়।
/app.js-এর মতো স্থির নাম আর লম্বা মেয়াদ হলে Deploy-এর পর ফিরে আসা ব্যবহারকারীর Browser-এ নতুন HTML চলে পুরনো JavaScript-এর সাথে, আর তাদের কপির মেয়াদ না ফুরোনো পর্যন্ত Server থেকে তুমি কিছুই করতে পারবে না। Query String-এ Version (app.js?v=42) Browser-এ চলে, কিন্তু কিছু Proxy Query String-ওয়ালা URL Cache করে না, আর নম্বর বাড়াতে ভুলে যাওয়াও সহজ; File-এর নামে Content Hash-ই মজবুত পথ। immutable মূলত Firefox আর Safari-তে কাজে লাগে: ২০১৭ থেকে Chrome সাধারণ Reload-এ আর Subresource যাচাই করে না, তাই সে Directive-টা উপেক্ষা করে।
Cache-এ থাকা Asset নিয়ে Deploy: File-এর নামে Hash কেন
Deploy-এর আগে Browser-এর কাছে গতকালের File। Deploy HTML আর JavaScript একসাথে বদলায়। একটা স্থির নাম আর Content-এর Hash-ওয়ালা নাম তুলনা করো।
পরিস্থিতি
/app.js-এ max-age=86400 (এক দিন), আর HTML-এ no-cache।
Release HTML-এ একটা Cart বোতাম যোগ করে, আর /app.js-এ renderCart Function।
#কী Cache করবে: প্রতিটা ধরনের Response-এর জন্য Policy
একটাই সঠিক Header বলে কিছু নেই; প্রতিটা ধরনের Response-এর জন্য একটা সঠিক Header আছে। ভালো একটা শুরুর সেট:
| Response | Cache-Control | কেন |
|---|---|---|
| Hash-ওয়ালা Static File (JS, CSS, Font, Hash-ওয়ালা ছবি) | public, max-age=31536000, immutable | Content বদলালে নামও বদলায় |
স্থির URL-এর Static File (/favicon.ico, /logo.png, /robots.txt) | max-age=3600 থেকে এক দিন, ETag সহ | নাম বদলানো যায় না, তাই মেয়াদ মাঝারি রাখো |
| Public HTML Page | ETag সহ no-cache; CDN-এ s-maxage=60, stale-while-revalidate=300, সাথে Deploy-এ Purge | নতুন Asset-এর নাম দ্রুত ধরতে হবে |
| Public API পড়া (Product List, মুদ্রার দর) | ETag সহ max-age=30, s-maxage=60, stale-while-revalidate=30 | সবার জন্য এক; কয়েক সেকেন্ড পুরনো হলে সমস্যা নেই |
ব্যক্তিগত Page আর API Response (/account, /api/me) | ETag সহ private, no-cache (বা private, max-age=60) | Browser আবার ব্যবহার করতে পারে; কোনো Shared Cache রাখতে পারবে না |
| স্পর্শকাতর Data (Bank Statement, Token, চিকিৎসার রেকর্ড) | no-store | Disk-এ বা কোনো Cache-এ কিছুই থাকবে না |
লেখা (POST, PUT, PATCH, DELETE) | সাধারণত কিছু না, বা no-store | আবার ব্যবহার হয় না; সফল একটা লেখা ওই URL-এর Browser-এ জমা কপিকেও বাতিল করে |
| Error (404, 5xx) | ছোট স্পষ্ট মেয়াদ, যেমন max-age=10, বা no-store | না হলে 404 আন্দাজে Cache হতে পারে, আর অল্প সময়ের বিভ্রাট Cache-এ জমে যায় |
| স্থায়ী Redirect (301, 308) | পরীক্ষার সময় পরিমিত max-age | Browser এগুলো শক্ত করে মনে রাখে; ভুল একটা 301 বহুদিন আটকে থাকতে পারে |
আগে ভাবো Response কে দেখতে পারবে (এটা ঠিক করে private, public, no-store), তারপর কতটা পুরনো হলে চলে (মেয়াদ আর stale-* ঠিক করে), তারপর কীভাবে Update হবে (স্থির URL আর আবার যাচাই, নাকি Hash-ওয়ালা নাম)।
#লগইন করা আর ব্যক্তিগত Response নিরাপদে Cache করা
সবচেয়ে খারাপ Caching Bug ধীর Page না; ভুল মানুষের কাছে পৌঁছানো Page। নিয়মগুলো:
১. কে চাইছে তার ওপর যে Response নির্ভর করে, সেটা private (বা no-store)। কোনো Page ব্যক্তিগত কি না, CDN আন্দাজ করবে, এই ভরসা কখনো কোরো না।
২. Authorization Header-ওয়ালা Request-এর Response Shared Cache রাখতে পারে না, যদি না Response স্পষ্টভাবে public, s-maxage বা must-revalidate দিয়ে অনুমতি দেয়। ব্যক্তিগত Response-এ এগুলো যোগ কোরো না।
৩. Set-Cookie-ওয়ালা Response কখনো Shared Cache-কে রাখতে দিয়ো না। HTTP Standard এটা নিষেধ করে না, কিন্তু Cache-এ থাকা Response যদি একজনের Session Cookie বয়ে আনে, তাহলে যে-ই সেই কপি পাবে, সে ওই ব্যবহারকারী হিসেবে লগইন হয়ে যাবে। Nginx আর বেশিরভাগ CDN ডিফল্টে এমন Response Cache করে না; “সব Cache করো” নিয়ম আর নিজের বানানো Proxy প্রায়ই করে।
৪. শুধু File-এর Extension দেখে Cache কোরো না। Web Cache Deception CDN-কে ধোঁকা দিয়ে /account/x.css রাখিয়ে নেয়, যা একটা ঢিলেঢালা Router Account Page হিসেবে Render করে।
৫. Page ভাগ করো। Public কাঠামো (Layout, Product-এর Data) CDN-এ Cache করো, আর ব্যক্তিগত অংশ (নাম, Cart-এর সংখ্যা) আনো আলাদা একটা Private API Call দিয়ে। ঝুঁকি ছাড়াই Hit Ratio উঁচু থাকে।
৬. Logout-এর সময় Clear-Site-Data: "cache" Browser-কে ওই Site-এর Cache করা Data মুছে ফেলতে বলে, আর স্পর্শকাতর Page-এ no-store থাকলে শেয়ার করা Computer-এ পরে Back বোতাম সেগুলো দেখাতে পারে না।
যখন Shared Cache একজনের Page জমা রেখে দেয়
সবচেয়ে খারাপ Caching Bug ধীর Page না, ভুল মানুষকে দেখানো Page। রহিম Login করেছে; এক মিনিট পরে করিম একই CDN দিয়ে ঢুকল।
পরিস্থিতি
কেউ CDN-এ একটা নিয়ম দিয়েছে, যা Origin-এর Header না মেনে সব HTML ৫ মিনিট Cache করে।
রহিম নিজের Account Page খুলল। তার Session Cookie বলে দেয় সে কে।
#Caching-এর পরিচিত Bug
| লক্ষণ | কারণ | সমাধান |
|---|---|---|
| একজন ব্যবহারকারী আরেকজনের নাম বা Account দেখছে | “সব Cache করো” নিয়ম বা ভুল একটা public-এর কারণে Shared Cache ব্যক্তিগত Page রেখেছে (প্রায়ই Set-Cookie সহ) | ব্যক্তিগত Response-এ private / no-store; Session Cookie আর Set-Cookie থাকলে CDN Cache এড়িয়ে যাবে |
| কিছু Client পড়া যায় না এমন Script বা Page পাচ্ছে | Vary: Accept-Encoding ছাড়া Compressed Body Cache হয়েছে | Compression দর-কষাকষি করলে সবসময় Vary: Accept-Encoding পাঠাও |
| Deploy-এর পর ফিরে আসা ব্যবহারকারীর Page ভাঙা | স্থির নামের JS বা CSS, লম্বা মেয়াদে | Hash-ওয়ালা File-এর নাম; স্বল্পমেয়াদি HTML |
| Deploy-এর ঠিক পরে নতুন ভিজিটর ফাঁকা Page দেখছে | পুরনো HTML এখনো Cache-এ, পুরনো Asset মুছে ফেলা | পুরনো Asset কয়েক দিন রাখো; CDN-এ HTML Purge করো বা মেয়াদ কমাও |
| Fix-এর অনেক পরেও পুরনো Version, কেউ মেয়াদ দেয়নি | Last-Modified থেকে আন্দাজের Freshness | সব জায়গায় স্পষ্ট Cache-Control |
| CDN-এর Hit Ratio এক অঙ্কে | Vary: User-Agent বা Vary: Cookie, বা Key-তে Tracking Parameter | গুছানো মানে Vary দাও; অব্যবহৃত Query Parameter বাদ দাও |
| আবার যাচাই সবসময় 200 দেয়, কখনো 304 না | Server-ভেদে ETag আলাদা, বা App প্রতি Request-এ নতুন ETag বানায় | Content বা Version থেকে ETag, প্রতিটা Node-এ এক |
| সরিয়ে ফেলার পরও ভুল একটা Redirect ব্যবহারকারীদের কাছে থেকে যাচ্ছে | Browser-এ Cache হওয়া 301 | আগে 302/307 দিয়ে পরীক্ষা, তারপর পরিমিত max-age সহ 301/308 |
| একটা বিভ্রাট Cache থেকে ঘণ্টার পর ঘণ্টা Error Page হয়ে দেখা দিচ্ছে | Error Response লম্বা মেয়াদে Cache হয়েছে | Error-এর জন্য ছোট মেয়াদ বা Cache-ই না; ভালো কপি রাখতে stale-if-error |
#Caching-এর বাইরেও ETag: If-Match আর হারানো Update
যে ETag 304 সম্ভব করে, সেটাই API-র একটা পুরনো সমস্যাও মেটায়। দুজন একই Record খোলে, দুজনেই Edit করে, দুজনেই Save করে: দ্বিতীয় Save চুপচাপ প্রথমটা মুছে লেখে। এর নাম Lost Update।
Optimistic Concurrency-তে Client খোলার সময়ের ETag-টা ফেরত পাঠায়:
PUT /products/7 HTTP/1.1
If-Match: "7"
Content-Type: application/json
{"price": 120, "title": "Mug"}
- বর্তমান Version এখনো
"7"হলে Server পরিবর্তনটা বসায় আর নতুন ETag ফেরত দেয়। - এর মধ্যে অন্য কেউ বদলে থাকলে Server ফেরত দেয়
412 Precondition Failed, কিছুই বদলায় না। Client আবার Load করে, ব্যবহারকারীকে নতুন অবস্থা দেখায়, আবার চেষ্টা করে। - যে Server অন্ধভাবে মুছে লেখা নিষেধ করতে চায়, সে
If-Matchছাড়া লেখায় দেয়428 Precondition Required। PUT-এIf-None-Match: *মানে “না থাকলে তবেই তৈরি করো”, একটা নাম দাবি করার বা একটা Object একবারই লেখার নিরাপদ উপায়; Amazon S3 দুই রকম শর্তযুক্ত লেখাই সমর্থন করে।
Server-এ যাচাই আর লেখা একটাই অবিভাজ্য ধাপ হতে হবে, সাধারণত UPDATE … WHERE id = 7 AND version = 7, তারপর দেখা যে ঠিক একটা Row বদলেছে। ব্যবহারকারী যতক্ষণ ভাবছে ততক্ষণ কোনো Lock ধরা থাকে না, এজন্যই একে বলে Optimistic। এই Header দিয়ে API Design চলবে Chapter 26-এ, আর Transaction Isolation Database-এর Chapter-গুলোতে।
Caching-এর বাইরেও ETag: If-Match হারানো Update ঠেকায়
দুজন Admin একই Product Edit করছে। যে ETag 304 সম্ভব করেছিল, সেটাই Server-কে বলে দেয় কোন Version দেখে Edit করা হয়েছে।
পরিস্থিতি
কোনো শর্ত ছাড়া সাধারণ PUT।
Alice Product খুলল: Version ৭।
#Browser-এর অন্য Cache, সংক্ষেপে
- Back/Forward Cache (bfcache)। তুমি Back চাপলে Browser আগের Page-টা Memory থেকে, তার JavaScript-এর অবস্থাসহ চোখের পলকে ফিরিয়ে আনতে পারে। এটা HTTP Cache থেকে আলাদা।
unloadHandler ব্যবহার করা বা WebSocket খোলা রাখা Page বাদ পড়তে পারে, আরCache-Control: no-storeদিয়ে পাঠানো Page বহুদিন ধরেই বাদ পড়ত (Chrome এর কিছুকে অনুমতি দেওয়া শুরু করেছে)। Back-এ যাওয়া ধীর লাগলে Chrome DevTools-এর Application অংশে bfcache-এর একটা পরীক্ষা আছে। - Service Worker Cache। Site-এর নিজের Script Request মাঝপথে ধরে Cache API থেকে উত্তর দিতে পারে; Offline Web App আর “আগে Network, না পেলে Cache” কৌশল এভাবেই চলে। Script যা বলে এটা তা-ই করে, তাই এর Bug তোমারই Bug।
- Memory Cache আর Preload।
<link rel="preload">দিয়ে আনা বা চলতি Page-এ আগেই ব্যবহার হওয়া Resource Memory থেকে আবার ব্যবহার হয়, সাধারণ নিয়মে মেয়াদ ফুরোনোর পরেও কিছুক্ষণ।
#System Design-এ HTTP Caching
- আগে Edge-এ Cache করো। Browser বা CDN যে Request-এর উত্তর দেয়, সেটা কখনো তোমার Load Balancer, App Server বা Database পর্যন্ত পৌঁছায় না। ৯৯% Hit Ratio-র Static Asset হলো সবচেয়ে সস্তা Scaling-এর জয়।
- মাপকাঠি হলো Hit Ratio। Origin-এর চাপ = মোট Request × (১ − Hit Ratio)। প্রতিটা Path-এর জন্য আলাদা দেখো; কম হলে সাধারণত দোষী
Vary, Cookie আর Query String। - Browser-এ ছোট, CDN-এ লম্বা, বদলালে Purge। Browser Purge করা যায় না, CDN যায়।
s-maxageআর CDN-এর নিজস্ব Header এজন্যই। - API এমনভাবে বানাও যাতে Cache করা যায়। Public পড়া আর ব্যক্তিগত পড়া আলাদা রাখো (
/products/7বনাম/me/cart), ETag দাও, আর পড়ার জন্যGETব্যবহার করো, যাতে Cache সাহায্য করতে পারে (Lesson ২.২)। - চালু থাকা বনাম সঠিকতা, জেনেবুঝে বাছো।
stale-while-revalidateধীর Render ঢাকে,stale-if-errorবিভ্রাট ঢাকে,must-revalidateদুটোই মানা করে। প্রতিটা Endpoint-এর জন্য আলাদা ঠিক করো। - Caching একটা নিরাপত্তার সীমানাও। ব্যক্তিগত Data-র সামনে থাকা যেকোনো Shared Cache একটা Access Control তালিকার মতোই সাবধানে সাজাতে হয়।
- Interview-এর প্রশ্ন: “Deploy-এর পর ব্যবহারকারী নতুন JavaScript পাচ্ছে, কীভাবে নিশ্চিত করবে?” (Hash-ওয়ালা নাম, স্বল্পমেয়াদি HTML)। “
no-cacheবনামno-store?” “আমাদের CDN-এর Hit Ratio কম কেন?” (Vary, Cookie, Query String)। “দুজন Admin একে অপরের লেখা মুছে না দিক, কীভাবে?” (ETag +If-Match, 412)। Cache-aside, Write-through আর Eviction-এর প্রশ্ন Chapter 23-এ।
#নিজে করে দেখো
# See the caching headers of any URL (HEAD request)
curl -sI https://www.example.com/ | grep -iE 'cache-control|etag|last-modified|expires|age|vary'
# Revalidate by hand: copy the ETag from above and send it back
curl -sI https://www.example.com/ -H 'If-None-Match: "84238dfc8092e5d9c0dac8ef93371a07"'
# HTTP/2 304 means your copy is still good
# Same with a date
curl -sI https://www.example.com/ -H 'If-Modified-Since: Mon, 02 Nov 2026 00:00:00 GMT'
# Is a CDN serving from cache? Look for age, x-cache or cf-cache-status (hit / miss / expired / revalidated)
curl -sI https://www.cloudflare.com/ | grep -iE 'cf-cache-status|age|cache-control'
# Ask for Brotli, then for nothing, and compare content-encoding and vary
curl -sI https://www.example.com/ -H 'Accept-Encoding: br'
curl -sI https://www.example.com/
# Optimistic concurrency against your own API
curl -i -X PUT https://api.example.com/products/7 -H 'If-Match: "7"' \
-H 'Content-Type: application/json' -d '{"price":120}'
# 412 Precondition Failed if someone changed it first
Nginx-এ Policy বসানো (পুরো Config আছে Lesson ১.১৩-এ):
location /assets/ { # hashed files
add_header Cache-Control "public, max-age=31536000, immutable";
}
location = /index.html { # the page that names them
add_header Cache-Control "no-cache";
etag on;
}
location /api/me { # personal
add_header Cache-Control "private, no-cache";
proxy_pass http://app;
}
Browser-এ DevTools → Network খোলো, Reload দাও, আর Size কলামটা দেখো: “(memory cache)” আর “(disk cache)” হলো Fresh Hit, আর 304 Status সহ কয়েকশো Byte মানে আবার যাচাই। Disable cache টিক দিলে Page-টা প্রথমবারের ভিজিটরের চোখে দেখবে; সাধারণ Reload আর Hard Reload (Ctrl+Shift+R) তুলনা করো। Application → Back/forward cache দেখায় একটা Page bfcache-এর যোগ্য কি না।
#সারসংক্ষেপ
মূল শিক্ষা
- HTTP Caching ব্যবহারকারীর কাছেই Response আবার ব্যবহার করে। Fresh Hit-এর দাম শূন্য, 304-এর এক ছোট Round Trip, 200-এর পুরো Body। CDN-এর Hit Ratio ৯০% থেকে ৯৫% করলে Origin-এর চাপ অর্ধেক।
- Private Cache (Browser) একজনের Data রাখতে পারে; Shared Cache (Proxy, Gateway, CDN) কখনোই না। Browser-এর Cache Memory আর Disk দুটোই ব্যবহার করে, আর Site ধরে ভাগ করা।
- কপি Fresh যতক্ষণ বয়স মেয়াদের চেয়ে কম:
s-maxage(শুধু Shared) হারায়max-age-কে, আরmax-ageসবসময় হারায়Expires-কে;Ageআগের ধাপে কাটানো সময় গোনে; মেয়াদ না থাকলে CacheLast-Modified-এর পর থেকে যাওয়া সময়ের ১০% আন্দাজ করতে পারে। no-cache= রাখো কিন্তু প্রতিবার যাচাই;no-store= কখনো রেখো না;private= শুধু Browser;public= কদাচিৎ লাগে;must-revalidate= কখনো Stale না, বদলে Error;immutable= কখনো আবার যাচাই না।- Validation: ETag +
If-None-Match(পছন্দের; Strong বাW/Weak; প্রতিটা Server-এ এক) বাLast-Modified+If-Modified-Since(এক সেকেন্ডের মাপ) → 304 Not Modified, আপডেট হওয়া Header সহ, Body ছাড়া। VaryRequest-এর Header-কে Cache Key-তে যোগ করে: Compressed Response-এ সবসময়Accept-Encoding; Shared Cache-এ কখনো কাঁচাUser-AgentবাCookieনা।stale-while-revalidateসাথে সাথে দেয়, পেছনে Refresh করে;stale-if-errorবিভ্রাটের মধ্যেও Site চালু রাখে (মূলত CDN-এ)।max-age=31536000, immutable-ওয়ালা Hash-ওয়ালা File-এর নাম, সাথে স্বল্পমেয়াদি HTML, Deploy নিরাপদ করে; পুরনো Asset কয়েক দিন রেখে দাও।- ব্যক্তিগত Response:
privateবাno-store, Shared Cache-এ কখনোSet-Cookieনা, শুধু Extension দেখে কখনো Cache না। - ETag +
If-Matchহারানো Update-কে বানায় 412 Precondition Failed;428শর্ত দাবি করে;If-None-Match: *একবারই তৈরি করে।
আগে নিজে উত্তর দাও, তারপর ব্যাখ্যাটা পড়ো। ঠিক হলেও পড়ো, কারণ ভুল Option-গুলো কেন ভুল, সেটাও ওখানে আছে।
নিজেকে যাচাই করোপ্রশ্ন
Private Cache আর Shared Cache-এর পার্থক্য কী?
নিজেকে যাচাই করোপ্রশ্ন
একটা Response-এ Cache-Control: max-age=600 আছে, আর Expires এখন থেকে এক ঘণ্টা পরে। Browser-এ এটা কতক্ষণ Fresh?
নিজেকে যাচাই করোপ্রশ্ন
Cache-Control: no-cache একটা Cache-কে কী বলে?
নিজেকে যাচাই করোপ্রশ্ন
একটা Response-এ max-age=60, আর সেটা CDN থেকে Age: 45 নিয়ে এল। Browser-এ এটা আর কতক্ষণ Fresh?
নিজেকে যাচাই করোপ্রশ্ন
একটা Response-এ কোনো Cache-Control বা Expires নেই, কিন্তু Last-Modified ২০ দিন আগের। Cache কী করতে পারে?
নিজেকে যাচাই করোপ্রশ্ন
Stale কপি আবার যাচাই করতে Browser কোন দুটো Header ব্যবহার করবে?
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
একটা Request-এ If-None-Match আর If-Modified-Since দুটোই আছে। ETag আর মেলে না, কিন্তু তারিখ বলছে File বদলায়নি। Server কী করবে?
নিজেকে যাচাই করোপ্রশ্ন
304 Not Modified Response নিয়ে কোন কথাটা সঠিক?
নিজেকে যাচাই করোপ্রশ্ন
তোমার Site একটা Load Balancer-এর পেছনে তিনটা Server-এ চলে। আবার যাচাইয়ের Request প্রায় কখনো 304 পায় না। সবচেয়ে সম্ভাব্য কারণ কী?
নিজেকে যাচাই করোপ্রশ্ন
ETag “abc” আর W/“abc”-এর পার্থক্য কী?
নিজেকে যাচাই করোপ্রশ্ন
একটা দোকানের CDN Product Page দেয় Vary: User-Agent দিয়ে, আর Hit Ratio ৬%। সবচেয়ে ভালো সমাধান কী?
নিজেকে যাচাই করোপ্রশ্ন
একটা Site-এর কিছু ব্যবহারকারী জগাখিচুড়ি JavaScript পায়, বাকিরা ঠিক, আর প্রতিবার CDN Purge-এর পর তা বদলায়। যে Client চায়, Origin তাকে Brotli-তে Compress করে দেয়। কী নেই?
নিজেকে যাচাই করোপ্রশ্ন
s-maxage নিয়ে কোন দুটো কথা সঠিক?
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
একটা Product List API দেয় max-age=60, stale-while-revalidate=300। CDN-এ Cache হওয়ার ১০০ সেকেন্ড পরে একজন ব্যবহারকারী চাইল। কী হবে?
নিজেকে যাচাই করোপ্রশ্ন
Database বিভ্রাটের সময় Origin প্রতিটা Request-এ 503 দিচ্ছে। কোন Header CDN-কে শেষ ভালো Home Page দেখাতে থাকতে দেয়?
নিজেকে যাচাই করোপ্রশ্ন
একটা Endpoint সেই Stock-এর হিসাব দেয়, যা দেখে Payment নেওয়া হয়। Stale মান দেখালে বেশি বিক্রি হয়ে যেতে পারে। Origin-এ পৌঁছানো না গেলে কোন Directive Cache-কে Stale কপির বদলে Error দেওয়ায়?
নিজেকে যাচাই করোপ্রশ্ন
একটা দল /app.js দেয় max-age=86400 দিয়ে, আর HTML দেয় no-cache দিয়ে। একটা Release-এর পর ফিরে আসা ব্যবহারকারীরা দেখে “renderCart is not a function”। কেন?
নিজেকে যাচাই করোপ্রশ্ন
লম্বা সময় Cache থাকা Static Asset সহ Deploy নিরাপদ করে কোন দুটো অভ্যাস?
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
Firefox আর Safari-র মতো immutable Directive Chrome-এর এত লাগে না কেন?
নিজেকে যাচাই করোপ্রশ্ন
সব HTML Cache করার একটা CDN নিয়মে একটা Account Page ভুল করে Cache হয়ে গেল। অন্যের নাম দেখা ছাড়াও কোন জিনিসটা একে বিশেষ বিপজ্জনক করে?
নিজেকে যাচাই করোপ্রশ্ন
একটা ব্যক্তিগত Profile API কোন Header দেবে, যাতে Browser অল্প সময় আবার ব্যবহার করতে পারে কিন্তু কোনো CDN বা Proxy রাখতে না পারে?
নিজেকে যাচাই করোপ্রশ্ন
ডিফল্টে, Authorization Header-ওয়ালা Request-এর Response কি Shared Cache রাখতে পারে?
নিজেকে যাচাই করোপ্রশ্ন
এক আক্রমণকারী লগইন করা ব্যবহারকারীদের /account/profile.css-এর Link পাঠায়। পরে সে নিজেই URL-টা খুলে একজন শিকারের Account Page দেখে। কী ঘটেছে?
নিজেকে যাচাই করোপ্রশ্ন
এগুলোর কোন দুটো সাধারণত Cache-Control: no-store পাবে?
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
একটা ব্যস্ত Endpoint-এ CDN-এর Hit Ratio ৬০%। Engineer-রা সেটা ৯০% করল। ওই Endpoint-এ Origin-এর Request কতটা কমল?
নিজেকে যাচাই করোপ্রশ্ন
দুজন Admin Product ৭ খুলল (ETag “7”)। Alice If-Match: “7” দিয়ে Save করে সফল হলো। তারপর Bob তার Edit Save করল If-Match: “7” দিয়ে। API Bob-কে কী ফেরত দেবে?
নিজেকে যাচাই করোপ্রশ্ন
একটা API চায় Client যেন শর্ত ছাড়া একদমই লিখতে না পারে। If-Match ছাড়া একটা PUT-এ সে কোন Status Code দেবে?
নিজেকে যাচাই করোপ্রশ্ন
Back/Forward Cache নিয়ে কোন কথাটা সঠিক?
নিজেকে যাচাই করোপ্রশ্ন
Browser Cache-এ একটা Page Fresh আছে। ব্যবহারকারী Ctrl+Shift+R চাপল। Browser কী পাঠাবে?
নিজেকে যাচাই করোপ্রশ্ন
একটা Site তার Public Product Page-এ Vary: Cookie দেয়, আর প্রত্যেক ভিজিটরের কাছে একটা অনন্য ID-ওয়ালা Analytics Cookie আছে। CDN-এ কী হবে?
নিজেকে যাচাই করোপ্রশ্ন
ETag ব্যবহারের ভালো কারণ নয় কোনটা?