Technology Aug 29, 2026 · 9 min read

HTTP cache header-larını düzgün qurmaq

HTTP keşini “sürət düyməsi” kimi təsəvvür etmək rahatdır: max-age əlavə et, server yükü azalsın, səhifə də sürətlənsin. Problem ondadır ki, keş yanlış cavabı çox səmərəli şəkildə çoxalda da bilir. Bir istifadəçinin məlumatı başqasına görünəndə və ya köhnə HTML yeni JavaScript bundle-a işarə etməyənd...

DE
DEV Community
by Jamal Ali
HTTP cache header-larını düzgün qurmaq

HTTP keşini “sürət düyməsi” kimi təsəvvür etmək rahatdır: max-age əlavə et, server yükü azalsın, səhifə də sürətlənsin. Problem ondadır ki, keş yanlış cavabı çox səmərəli şəkildə çoxalda da bilir. Bir istifadəçinin məlumatı başqasına görünəndə və ya köhnə HTML yeni JavaScript bundle-a işarə etməyəndə qazandığımız bir neçə millisaniyə artıq təsəlli vermir.

Fərq vacibdir.

Düzgün siyasət header adlarını əzbərləməklə qurulmur. Əvvəl hər resurs üçün üç suala cavab lazımdır: cavab nə qədər müddət dəyişmədən qala bilər, onu kimlər paylaşa bilər və köhnələndə origin serverlə yoxlanmalıdırmı? Üç sual. Qalan seçimlər onların cavabından çıxır.

Keşin iki ayrı işi var

HTTP cache cavabı saxlaya və sonrakı uyğun request-də yenidən istifadə edə bilər. Browser cache adətən bir istifadəçiyə xidmət edən private cache-dir. CDN və reverse proxy isə bir cavabı çox istifadəçiyə verən shared cache rolundadır. Eyni Cache-Control sətri hər ikisinə təsir edə bilər, amma onların riskləri eyni deyil.

Burada iki anlayış tez-tez qarışır: freshness və validation. Fresh cavabın müəyyən edilmiş ömrü hələ bitməyib, ona görə cache origin-ə getmədən onu işlədə bilər. Stale cavabın ömrü bitib. Bu, cavabın mütləq yararsız olması demək deyil; validator varsa cache kiçik conditional request göndərib nüsxəsinin hələ aktual olub-olmadığını soruşa bilər. RFC 9111 HTTP cache davranışını məhz saxlama, freshness və validation qaydaları üzərindən müəyyənləşdirir.

max-age=300 cavabın yaradıldığı və ya son uğurlu validation edildiyi andan beş dəqiqə sonra stale sayılacağını bildirir. Beş dəqiqə ərzində cache hit origin-ə request göndərməyə bilər. Bu müddəti yalnız trafikə baxıb seçmək yarımçıq yanaşmadır, çünki əsas ölçü biznesin həmin cavabın köhnəlməsinə nə qədər dözə bilməsi və yanlış məlumatın hansı əməliyyata təsir göstərməsidir.

Cache-Control: public, max-age=300

public cavabı açıq şəkildə cacheable edir və shared cache üçün də istifadəyə imkan yaradır. Hər public resursa bu direktivi əlavə etmək məcburi deyil, çünki bəzi cavablar onsuz da cacheable olur; API və CDN konfiqurasiyasında niyyəti aydın göstərmək isə yenə faydalıdır.

no-cache, no-store və private eyni şey deyil

Adına görə ən çox çaşdıran direktiv no-cache-dir. Cavabı saxlamağı qadağan etmir. Cache saxlanmış cavabı yenidən verməzdən əvvəl origin serverdə uğurla validate etməlidir. Bu, tez-tez dəyişən HTML üçün yaxşı seçim ola bilər: browser nüsxəni saxlayır, ETag ilə soruşur, məzmun dəyişməyibsə server body əvəzinə 304 Not Modified qaytarır.

Cache-Control: no-cache
ETag: "page-v42"

ETag cavab variantının identifikatorudur. Növbəti request If-None-Match header-ı ilə gedir. Serverdə təqdimat eynidirsə bütün body yenidən daşınmır, amma network gediş-gəlişi qalır; deməli validation bandwidth-i azalda bilər, latency-ni sıfırlamır.

no-store daha sərtdir: cache request və response-u saxlamamalı, həmin response-u başqa request-i cavablandırmaq üçün istifadə etməməlidir. Bank çıxarışı, birdəfəlik token və həssas şəxsi məlumat kimi cavablarda məntiqlidir. Bununla belə, no-store şifrələmə və access control əvəzi deyil, komprometasiya edilmiş cache və ya şəbəkədə dinləmə riskini bu header təkbaşına həll etmir.

private başqa sərhəd çəkir. Shared cache cavabı saxlamır, istifadəçinin private cache-i isə digər şərtlər imkan verirsə saxlaya bilər. Login olmuş istifadəçinin profil səhifəsi dəyişməz deyil, amma hər naviqasiyada bütün body-ni yenidən daşımaq da lazım olmaya bilər:

Cache-Control: private, no-cache
ETag: "profile-8d91"

Bu kombinasiya browser-ə cavabı saxlamağa, hər istifadədən əvvəl isə yoxlamağa imkan verir. Təkcə Set-Cookie görüb response-un cache edilməyəcəyini düşünmək təhlükəlidir, çünki Set-Cookie özü caching-i dayandırmır və siyasət Cache-Control ilə açıq yazılmalıdır.

Browser və CDN üçün ayrı ömür

Bəzən browser-in cavabı qısa müddət saxlaması, CDN-in isə daha uzun saxlaması məqsədəuyğundur. s-maxage yalnız shared cache üçün maksimum yaşı müəyyən edir və həmin cache-də max-age və Expires dəyərini üstələyir.

Cache-Control: public, max-age=60, s-maxage=600

Bu nümunədə browser bir dəqiqəlik freshness görür, CDN isə cavabı on dəqiqə fresh saya bilər. Risk də böyüyür. Daha uzun CDN ömrü bütün istifadəçilərə köhnə məlumat yayır, buna görə endpoint-in cavabı regiona, dilə və ya başqa request header-ına görə dəyişirsə cache key həmin fərqi mütləq bilməlidir.

Vary: Accept-Encoding cache-ə sıxılma variantlarını ayırmağı deyir. Vary: Accept-Language dilə görə ayrıca variant yaradır. Vary-də göstərilən request header-ları uyğun gəlmirsə saxlanmış cavab yoxlanmadan istifadə edilə bilməz. Hər şeyi Vary-yə əlavə etmək çıxış yolu deyil, variantların sayı artdıqca hit ratio düşür, cache-in faydası əriyir və xüsusən Vary: User-Agent çox geniş kombinasiya yarada bilər.

İstifadəçiyə görə dəyişən cavabı shared cache-də saxlamaq istəyərkən məsələ daha qəlizdir. Cache key həqiqətən istifadəçini ayırmırsa, public və uzun s-maxage təhlükəli seçimdir. Belə cavabı private saxlamaq və ya public hissə ilə fərdi hissəni ayrı endpoint-lərə bölmək daha aydın sərhəd yaradır.

Statik asset və HTML fərqli ömür istəyir

Content hash daşıyan app.a81f3c.js faylının məzmunu dəyişəndə adı da dəyişir. Bu tip immutable asset üçün uzun freshness uyğundur:

Cache-Control: public, max-age=31536000, immutable

Köhnə faylı zorla invalidasiya etməyə ehtiyac qalmır. Yeni deploy yeni URL yaradır, HTML də həmin URL-ə işarə edir. Amma hash daşımayan /app.js üçün eyni birillik siyasət deploy-dan sonra köhnə kodun uzun müddət qalmasına səbəb ola bilər; cache busting query parametrindən istifadə edilirsə parametr hər məzmun dəyişikliyində sabit qayda ilə dəyişməlidir.

HTML isə adətən qısa freshness və ya validation istəyir, çünki yeni asset ünvanlarını o daşıyır. HTML uzun müddət köhnə qalsa, serverdə artıq silinmiş bundle-a request gedə bilər. Release prosesi köhnə asset-ləri bir müddət saxlamaqla bu keçidi yumşalda bilər, lakin əsas siyasət yenə resursların dəyişmə modelinə uyğun olmalıdır.

Expires eyni məqsəd üçün tarix verir, amma max-age olduqda recipient Expires-ı nəzərə almır. Müasir konfiqurasiyada nisbi saniyə dəyəri deploy və saat fərqləri baxımından daha rahatdır. Header ümumiyyətlə verilməyəndə bəzi cache-lər heuristic freshness hesablaya bilər; davranışı infrastruktura buraxmaqdansa niyyəti açıq yazmaq daha proqnozlaşdırılandır.

Siyasəti production-da görmək

Konfiqurasiya faylında düzgün görünən header yolun sonunda dəyişə bilər. CDN qaydası origin header-ını əvəz edir, framework middleware-i yalnız bəzi status kodlarına işləyir, reverse proxy isə Vary sahəsini itirir. Ona görə yoxlama browser devtools ilə bitmir. Origin və CDN cavabları ayrıca izlənir, Age, Cache-Control, ETag, Vary və status kodu birlikdə oxunur.

Age shared cache-də cavabın təxmini yaşını saniyə ilə göstərir. Ardıcıl request-lərdə artması cavabın origin-dən yox, aradakı cache-dən gəldiyinə işarə edə bilər. Validation baş verəndə 304, fresh hit zamanı isə çox vaxt normal status və cache vendor-una aid əlavə hit header-ı görünür.

Keş siyasəti endpoint növünə görə sənədləşdiriləndə dəyişikliklər də təhlükəsiz olur: hashed asset uzunömürlüdür, HTML validate edilir, public kataloq cavabı qısa müddət shared cache-də qalır, şəxsi məlumat isə shared cache-dən uzaq tutulur. Eyni universal header daha az konfiqurasiya kimi görünür. Sonradan açdığı başağrısı isə xeyli universaldır.

Tez-tez verilən suallar

no-cache cavabın saxlanmasını qadağan edirmi?

Xeyr. no-cache cavabın sonrakı request üçün istifadə edilməzdən əvvəl origin serverdə uğurla yoxlanmasını tələb edir.

no-store ilə private arasında fərq nədir?

no-store cavabın cache-də saxlanmasını qadağan edir. private isə shared cache-i kənarda saxlayır, amma istifadəçinin browser cache-inə saxlamağa icazə verə bilər.

Dəyişməz statik fayllara uzun max-age vermək təhlükəlidirmi?

Faylın URL-i content hash və ya versiya daşıyırsa təhlükə xeyli azalır, çünki məzmun dəyişəndə URL də dəyişir. Eyni URL altında məzmun dəyişəcəksə uzun ömür uyğun deyil.

Mənbələr

DE
Source

This article was originally published by DEV Community and written by Jamal Ali.

Read original article on DEV Community
Back to Discover

Reading List