Flutter कैशिंग रणनीतियाँ: लोकल कैश, स्टेल डेटा, और रिफ्रेश नियम — क्या स्टोर करें, कब अमान्य करें, और स्क्रीन को सुसंगत कैसे रखें।

मोबाइल ऐप में कैशिंग का मतलब है डेटा की नज़दीकी कॉपी रखना (मेमोरी या डिवाइस पर) ताकि अगला स्क्रीन तुरंत रेंडर हो सके बिना नेटवर्क के इंतज़ार के। यह डेटा किसी आइटम की सूची, यूज़र प्रोफ़ाइल, या खोज परिणाम हो सकता है।
मुश्किल इसलिए आती है क्योंकि कैश किया गया डेटा अक्सर थोड़ा पुराना होता है। यूज़र्स जल्दी नोटिस कर लेते हैं: कीमत नहीं बदलती, बैज काउंट अटका महसूस होता है, या डिटेल स्क्रीन पर पुराने जानकारी दिखती है ठीक बाद में जब उन्होंने बदलाव किया हो। इसे डिबग करना मुश्किल बनता है क्योंकि टाइमिंग मायने रखती है—समान एंडपॉइंट pull-to-refresh पर ठीक दिख सकता है, पर back navigation, ऐप resume, या अकाउंट बदलने पर गलत लग सकता है।
एक tradeoff है। अगर आप हमेशा ताज़ा डेटा फेच करेंगे तो स्क्रीन धीमी और जंपy लगेगी और बैटरी/डेटा बेकार खर्च होगा। अगर आप ज़्यादा आक्रामक तरीके से कैश करेंगे तो ऐप तेज लगेगा पर लोग उस पर भरोसा खो देंगे।
एक सरल लक्ष्य मदद करता है: freshness को predictable बनाओ। तय करो कि हर स्क्रीन क्या दिखा सकती है (ताज़ा, थोड़ा स्टेल, या ऑफ़लाइन), डेटा कितनी देर तक रहेगा, और कौनसे इवेंट उसे अमान्य बना देंगे।
एक आम फ्लो की कल्पना करो: यूज़र एक ऑर्डर खोलता है, फिर ऑर्डर लिस्ट पर वापस जाता है। अगर लिस्ट कैश से आ रही है तो वह पुरानी status दिखा सकती है। अगर हर बार रिफ्रेश करोगे तो लिस्ट flicker करेगी और धीमी लगेगी। साफ़ नियम जैसे “कैश तुरंत दिखाओ, बैकग्राउंड में रीवैलिडेट करो, और जब रिस्पॉन्स आए तो दोनों स्क्रीन अपडेट करो” एक्सपीरियंस को नेविगेशन के दौरान लगातार बनाते हैं।
कैश सिर्फ “सेव किया हुआ डेटा” नहीं है। यह एक कॉपी है और एक नियम कि वह कॉपी कब वैध है। अगर आप payload स्टोर कर लेते हैं पर नियम नहीं रखते, तो दो अलग हकीकतें बन जाएंगी: एक स्क्रीन नया दिखाएगी, दूसरी कल का।
एक व्यावहारिक मॉडल यह है कि हर cached आइटम को तीन अवस्थाओं में डालें:
यह framing आपकी UI को predictable रखती है क्योंकि यह हर बार एक जैसी प्रतिक्रिया दे सकती है जब वह किसी state को देखे।
Freshness नियमों को ऐसे संकेतों पर आधारित होना चाहिए जिन्हें आप teammate को समझा सको। आम विकल्प हैं: समय-आधारित expiry (जैसे 5 मिनट), वर्शन बदलना (schema या app version), यूज़र एक्शन (pull to refresh, submit, delete), या सर्वर संकेत (ETag, last-updated timestamp, या explicit “cache invalid” प्रतिक्रिया)।
उदाहरण: प्रोफ़ाइल स्क्रीन cached यूज़र डेटा तुरंत लोड करती है। अगर वो स्टेल पर उपयोगी है तो cached नाम और अवतार दिखाती है और चुपचाप refresh कर लेती है। अगर यूज़र अभी-अभी प्रोफ़ाइल edit कर चुका है, तो यह एक मस्ट-रिफ्रेश मोमेंट है। ऐप को cache तुरंत अपडेट करना चाहिए ताकि हर स्क्रीन सुसंगत रहे।
ये नियम किसका जिम्मा है तय करें। ज़्यादातर ऐप्स में बेस्ट डिफ़ॉल्ट यह है: डेटा लेयर freshness और invalidation की देखरेख करे, UI सिर्फ प्रतिक्रिया दे (cached दिखाओ, लोडिंग दिखाओ, एरर दिखाओ), और backend जब संभव हो hints दे। इससे हर स्क्रीन अपना नियम नहीं बनाएगी।
अच्छी कैशिंग एक सवाल से शुरू होती है: अगर यह डेटा थोड़ा पुराना है तो क्या यूज़र को नुकसान होगा? अगर जवाब “शायद ठीक है” है तो आमतौर पर लोकल कैश के लिए ठीक है।
वे डेटा जो अक्सर पढ़े जाते हैं और धीरे-धीरे बदलते हैं, आमतौर पर कैश के लिए उपयुक्त हैं: स्क्रोल करने वाले फीड/लिस्ट, कैटलॉग-सार content (products, articles), और संदर्भ डेटा जैसे categories या देशों की सूची। सेटिंग्स और प्रेफरेंस भी यहाँ आते हैं, साथ में बेसिक प्रोफ़ाइल जानकारी जैसे नाम और अवतार URL।
जो रिस्की है वह है पैसा या समय-संवेदी डेटा। बैलेंस, पेमेंट स्टेटस, स्टॉक उपलब्धता, अपॉइंटमेंट स्लॉट्स, डिलिवरी ETAs और “last seen online” जैसे मैट्रिक्स स्टेल होने पर असली समस्याएं पैदा कर सकते हैं। आप इन्हें स्पीड के लिए कैश कर सकते हैं, पर निर्णय बिंदुओं (जैसे ऑर्डर कन्फर्म करने से ठीक पहले) पर कैश को अस्थायी placeholder समझें और रिफ्रेश करें।
Derived UI state अलग कैटेगरी है। चुना हुआ टैब, फ़िल्टर, खोज क्वेरी, सॉर्ट ऑर्डर, या स्क्रॉल पोजीशन सेव करने से नेविगेशन स्मूद लगता है। पर यह भी लोगों को confuse कर सकता है जब पुराने चुनाव अनपेक्षित रूप से फिर से दिखें। एक सरल नियम काम करता है: UI state को स्मृति (in-memory) में रखें जब तक यूज़र उसी फ्लो में रहता है, पर जब वे जानबूझकर “शुरू से” लौटते हैं (जैसे होम स्क्रीन पर वापस) तो reset कर दें।
सिक्योरिटी/प्राइवेसी रिस्क वाले डेटा को कैश करने से बचें: secrets (passwords, API keys), one-time tokens (OTP, password reset tokens), और संवेदनशील पर्सनल डेटा जब तक वास्तव में ऑफ़लाइन एक्सेस की ज़रूरत न हो। पूरा कार्ड विवरण कभी कैश न करें।
शॉपिंग ऐप में, product list कैश करना बड़ा फायदा है। पर checkout स्क्रीन में हमेशा totals और availability सर्वर से कन्फर्म करें खरीद से ठीक पहले।
ज़्यादातर Flutter ऐप्स को लोकल कैश की ज़रूरत पड़ती है ताकि स्क्रीन तेज़ लोड हों और नेटवर्क के जागने पर खाली न दिखें। महत्वपूर्ण निर्णय यह है कि कैश कहां रखे जाएँ—हर लेयर की स्पीड, साइज लिमिट और cleanup व्यवहार अलग होता है।
एक memory cache सबसे तेज़ है। यह उन्हीं डेटा के लिए अच्छा है जो आपने अभी फेच किया है और ऐप खुला रहते हुए फिर से उपयोग होगा, जैसे current user profile, आखिरी खोज परिणाम, या अभी देखा गया product। इसका tradeoff स्पष्ट है: ऐप kill होते ही यह गायब हो जाता है, इसलिए cold starts या ऑफ़लाइन के लिए मददगार नहीं होगा।
Disk key-value स्टोरेज उन छोटे आइटमों के लिए ठीक है जिन्हें आप restarts के बाद रखना चाहते हैं। सोचें preferences और छोटे blobs: feature flags, “last selected tab”, और छोटे JSON responses जो बार-बार नहीं बदलते। इसे जानबूझकर छोटा रखें। बड़े लिस्ट्स key-value में डालने से updates उलझन और bloat हो सकता है।
लोकल डेटाबेस सबसे अच्छा तब है जब आपका डेटा बड़ा, संरचित, या ऑफ़लाइन व्यवहार चाहिए। यह क्वेरी करने में भी मदद करता है ("सारे unread messages", "cart में आइटम", "पिछले महीने के ऑर्डर्स") बजाय कि एक बड़ा blob लोड कर के मेमोरी में फिल्टर करने के।
कैशिंग को predictable रखने के लिए, हर डेटा प्रकार के लिए एक primary स्टोर चुनें और एक ही dataset को तीन जगह न रखें।
त्वरित नियम:
साथ ही साइज का प्लान बनाएं। तय करें “बहुत बड़ा” क्या है, आप आइटम कितनी देर रखेंगें, औरCleanup कैसे होगा। उदाहरण: cached search results को आखिरी 20 क्वेरीज तक सीमित रखें, और 30 दिनों से पुराने रिकॉर्ड नियमित रूप से हटाएँ ताकि कैश अनियंत्रित न बढ़े।
Refresh नियम इतने सरल होने चाहिए कि आप उन्हें हर स्क्रीन के लिए एक वाक्य में समझा सकें। यहीं से sensible caching का फायदा मिलता है: यूज़र्स को तेज स्क्रीन मिलती हैं और ऐप भरोसेमंद रहता है।
सबसे सरल नियम TTL (time to live) है। डेटा को एक timestamp के साथ स्टोर करें और उसे, उदाहरण के लिए, 5 मिनट तक ताज़ा मानें। उसके बाद वह stale हो जाता है। TTL उन “nice to have” डेटा के लिए अच्छा है जैसे feed, categories, या recommendations।
एक उपयोगी संशोधन soft TTL और hard TTL को अलग करना है।
soft TTL के साथ आप cached डेटा तुरंत दिखाते हैं, फिर बैकग्राउंड में refresh करते हैं और UI तब ही redraw करते हैं जब कुछ बदलता है। hard TTL में आप expired पुराने डेटा दिखाना बंद कर देते हैं—या तो loader दिखाएँ या “ऑफ़लाइन/ट्राय अगेन” दिखाएँ। Hard TTL उन मामलों के लिए है जहाँ गलत होना धीमा होने से ज्यादा खराब है, जैसे बैलेंस, ऑर्डर स्टेटस, या permissions।
अगर आपका backend समर्थित है तो “refresh only when changed” (ETag, updatedAt, या version फ़ील्ड) को प्राथमिकता दें। आपकी ऐप पूछ सकती है “क्या यह बदला है?” और जब कुछ नया न हो तो पूरा payload डाउनलोड करने से बच सकती है।
यूज़र-फ्रेंडली डिफ़ॉल्ट अक्सर stale-while-revalidate होता है: अभी दिखाओ, चुपचाप refresh करो, और केवल अगर परिणाम अलग हो तो redraw करो। यह स्पीड देता है बिना अनावश्यक flicker के।
प्रति-स्क्रीन freshness अक्सर कुछ इस तरह दिखती है:
नियम चुनते समय गलत होने की लागत पर ध्यान दें, सिर्फ़ फेच करने की लागत पर नहीं।
Cache invalidation यह सवाल पूछकर शुरू होती है: कौनसा इवेंट cached डेटा को इतना अविश्वसनीय बना देता है कि refetch करने की लागत वाजिब है? अगर आप कुछ छोटे ट्रिगर्स चुनकर और उन पर कायम रहेंगे तो व्यवहार predictable रहेगा और UI स्थिर महसूस होगा।
ऐप्स में जो ट्रिगर्स सबसे ज़्यादा मायने रखते हैं:
उदाहरण: यूज़र ने प्रोफ़ाइल फ़ोटो edit की और फिर वापस गया। अगर आप केवल समय-आधारित refresh पर भरोसा करते हैं तो previous स्क्रीन पुरानी इमेज दिखा सकती है जब तक अगला फेच न हो। इसके बजाय edit को trigger मानें: cached profile ऑब्जेक्ट तुरंत अपडेट करें और इसे नई timestamp के साथ ताज़ा मार्क करें।
इनवैलिडेशन नियम छोटे और स्पष्ट रखें। अगर आप किसी cache एंट्री को अमान्य करने वाला सटीक इवेंट नहीं बता सकते, तो आप बहुत बार रिफ्रेश करेंगे (धीमा, जंपy UI) या पर्याप्त नहीं रिफ्रेश करेंगे (स्टेल स्क्रीन)।
शुरू करें अपने मुख्य स्क्रीन की सूची बनाकर और हर स्क्रीन को जो डेटा चाहिए वह लिखकर। endpoints के बारे में मत सोचो; user-visible objects के बारे में सोचो: profile, cart, order list, catalog item, unread count।
अगला, हर डेटा प्रकार के लिए एक source of truth चुनें। Flutter में यह आमतौर पर एक repository होता है जो छिपाता है कि डेटा कहाँ से आता है (मेमोरी, डिस्क, नेटवर्क)। स्क्रीनें नेटवर्क मारने का निर्णय नहीं लें; वे repository से डेटा माँगें और लौटे हुए state पर प्रतिक्रिया करें।
एक व्यावहारिक फ्लो:
मेटाडेटा वही है जो नियमों को लागू करने योग्य बनाता है। अगर ownerUserId बदलता है (logout/login), आप पुराने cached rows तुरंत drop या ignore कर सकते हैं बजाय इसके कि पिछले यूज़र का डेटा एक split सेकंड के लिए दिखे।
UI व्यवहार के लिए पहले तय करें कि “stale” का क्या मतलब है। एक सामान्य नियम: stale डेटा तुरंत दिखाएँ ताकि स्क्रीन खाली न रहे, बैकग्राउंड में रिफ्रेश ट्रिगर करें, और नई डेटा आने पर अपडेट करें। अगर रिफ्रेश फेल हो, तो stale डेटा दिखाते रहें और एक छोटा, स्पष्ट एरर दिखाएँ।
फिर नियमों को कुछ बुनियादी टेस्ट्स से लॉक करें:
यही फर्क है “हमारे पास कैशिंग है” और “हमारा ऐप हर बार एक जैसा व्यवहार करता है” के बीच।
सबसे ज्यादा भरोसा तब टूटता है जब आप लिस्ट स्क्रीन पर एक वैल्यू देखते हैं, डिटेल खोलते हैं, उसे edit करते हैं, और वापस आते समय पुरानी वैल्यू दिखती है। नेविगेशन में सुसंगति उहीँ से आती है कि हर स्क्रीन एक ही source पढ़े।
एक ठोस नियम है: एक बार फेच करो, एक बार स्टोर करो, कई बार रेंडर करो। स्क्रीनें उसी endpoint को अलग-अलग तरीके से न कॉल करें और निजी कॉपी न रखें। cached डेटा को shared store (आपके state management लेयर) में रखें, और लिस्ट व डिटेल दोनों वही डेटा observe करें।
एक ही जगह रखें जो current value और freshness की मालिक हो। स्क्रीन रिफ्रेश माँग सकती हैं, पर अपनी timers, retries, और parsing खुद न संभालें।
कुछ व्यवहार जो “दो हकीकतें” होने से बचाते हैं:
अच्छे नियमों के बावजूद, यूज़र्स कभी-कभी stale डेटा देखेंगे (ऑफ़लाइन, धीला नेटवर्क, बैकग्राउंड्ड ऐप)। इसे छोटे, शांत संकेतों से स्पष्ट करें: “Updated just now” timestamp, एक सूक्ष्म “Refreshing…” indicator, या “Offline” बैज।
Edits के लिए optimistic updates अक्सर बेहतर महसूस होते हैं। उदाहरण: यूज़र डिटेल स्क्रीन पर किसी प्रोडक्ट की कीमत बदलता है। shared store को तुरंत अपडेट करें ताकि लिस्ट पर वापस आते ही नई कीमत दिखे। अगर save फेल हो, तो पिछला वैल्यू रोलबैक करें और छोटा एरर दिखाएँ।
ज़्यादातर कैशिंग फेल्यर साधारण होते हैं: कैश काम कर रहा है, पर कोई यह नहीं बता सकता कि कब उपयोग करना है, कब expire होता है, और किसका मालिक है।
पहला जाल metadata के बिना कैश करना है। अगर आप सिर्फ payload स्टोर करते हैं, तो आप यह नहीं बता पाएँगे कि यह पुराना है, किस app version ने इसे बनाया, या यह किस user का है। कम से कम savedAt, एक साधारण version number, और userId (या tenant key) सेव करें। यह आदत many “यह स्क्रीन गलत क्यों है?” बग रोकती है।
एक और आम समस्या वही डेटा के लिए कई कैश हैं जिनका कोई मालिक नहीं। एक लिस्ट स्क्रीन इन-मेमोरी रखती है, एक repository डिस्क में लिखता है, और डिटेल स्क्रीन फिर से फेच करके कहीं और सेव कर देता है। एक source of truth चुनें (अक्सर repository लेयर) और हर स्क्रीन उसे पढ़े।
अकाउंट बदलना अक्सर पिटफॉल है। अगर कोई logout या अकाउंट बदलता है तो user-scoped tables और keys साफ़ करें। अन्यथा आप पिछले यूज़र की प्रोफ़ाइल फोटो या ऑर्डर्स कुछ सेकंड के लिए दिखा सकते हैं, जो प्राइवेसी का जोखिम है।
प्रायोगिक fixes जो ऊपर की समस्याओं को कवर करते हैं:
उदाहरण: आपका product list तुरंत कैश से लोड होता है, फिर चुपचाप refresh होता है। अगर refresh फेल हो, तो cached डेटा दिखाई देता रहे पर स्पष्ट कर दें कि यह पुराना हो सकता है और Retry ऑफर करें। UI को refresh पर block न करें जब cached डेटा ठीक हो।
रिलीज़ से पहले, कैशिंग को “ठीк लगता है” से नियमों में बदल दें जिन्हें आप टेस्ट कर सकें। यूज़र्स को अर्थपूर्ण डेटा दिखना चाहिए भले ही उन्होंने आगे-पीछे नेविगेट किया हो, ऑफ़लाइन गए हों, या अलग अकाउंट से साइन इन किया हो।
हर स्क्रीन के लिए तय करें कि डेटा कितनी देर तक ताज़ा माना जाएगा। यह fast-moving डेटा के लिए मिनट हो सकता है (messages, balances) या slow-changing डेटा के लिए घंटे (settings, product categories)। फिर पुष्टि करें कि जब यह ताज़ा न रहे तो क्या होता है: बैकग्राउंड refresh, open पर refresh, या मैनुअल pull-to-refresh।
हर डेटा टाइप के लिए तय करें कि कौनसे इवेंट कैश को wipe या bypass करेंगे। सामान्य ट्रिगर्स में logout, आइटम edit, अकाउंट स्विच, और ऐप अपडेट शामिल हैं जो डेटा का स्वरूप बदलते हैं।
सुनिश्चित करें कि cached एंट्रीज़ के साथ छोटा metadata सेट सेव हो:
Ownership साफ रखें: हर डेटा टाइप के लिए एक repository (उदा., ProductsRepository) इस्तेमाल करें, widget के लिए नहीं। Widgets को डेटा माँगना चाहिए, cache नियम तय नहीं करने चाहिए।
ऑफ़लाइन व्यवहार भी तय और टेस्ट करें। पुष्टि करें कि स्क्रीन कैश से क्या दिखाएंगी, कौनसे actions disabled होंगे, और क्या कॉपी दिखेगी ("Showing saved data" के साथ refresh कंट्रोल)। मैनुअल refresh हर cache-backed स्क्रीन पर मौजूद और आसानी से मिलना चाहिए।
एक साधारण शॉप ऐप की कल्पना करें जिसमें तीन स्क्रीन हैं: product catalog (list), product details, और Favorites टैब। यूज़र catalog स्क्रोल करते हैं, एक product खोलते हैं, और heart आइकन पर टैप करके favorite करते हैं। उद्देश्य है कि धीले नेटवर्क पर भी तेज़ महसूस हो और confusing mismatches न हों।
लोकली वे चीज़ें कैश करें जो तुरंत रेंडर करने में मदद करें: catalog पेजेस (IDs, title, price, thumbnail URL, favorite flag), product details (description, specs, availability, lastUpdated), image metadata (URLs, sizes, cache keys), और यूज़र के favorites (product IDs का सेट, वैकल्पिक timestamps के साथ)।
जब यूज़र catalog खोलता है, cached results तुरंत दिखाएँ और बैकग्राउंड में revalidate करें। अगर ताज़ा डेटा आता है, केवल बदले हुए हिस्सों को अपडेट करें और स्क्रॉल पोजीशन स्थिर रखें।
Favorite toggle को “मस्ट कंसिस्टेंट” एक्शन मानो। लोकली favorites सेट तुरंत अपडेट करो (optimistic update), फिर किसी भी cached product row और cached product details को अपडेट करो। अगर नेटवर्क कॉल फेल हो, तो rollback करो और छोटा संदेश दिखाओ।
नेविगेशन सुसंगत रखने के लिए list badges और details heart आइकन दोनों को एक ही source of truth (लोकल कैश/स्टोर) से चलाओ, न कि अलग स्क्रीन स्टेट से। लिस्ट का हार्ट तुरंत अपडेट हो जब आप डिटेल से लौटते हैं, डिटेल स्क्रीन लिस्ट से किए गए बदलाव दिखाती है, और Favorites टैब की गिनती हर जगह मेल खाती है बिना किसी refetch के।
सरल refresh नियम जोड़ें: catalog कैश जल्दी expire होता है (मिनटों में), product details थोड़ा लंबा, और favorites कभी expire न हों पर login/logout के बाद reconcile हों।
कैशिंग तब रहस्यमय होना बंद कर देती है जब आपकी टीम एक पेज नियम को दिखा सके और इस पर सहमत हो कि क्या होगा। लक्ष्य परफेक्शन नहीं है — लक्ष्य predictable व्यवहार है जो रिलीज के बाद भी एक जैसा रहे।
हर स्क्रीन के लिए एक छोटा टेबल लिखो और इसे परिवर्तन के दौरान रिव्यू करने लायक छोटा रखो: स्क्रीन नाम और मुख्य डेटा, कैश स्थान और key, freshness नियम (TTL, event-based, या manual), invalidation ट्रिगर्स, और रिफ्रेश के दौरान यूज़र क्या देखेगा।
ट्यूनिंग के दौरान हल्का logging जोड़ें। cache hits, misses, और किस वजह से refresh हुआ (TTL expired, user pulled to refresh, app resumed, mutation completed) रिकॉर्ड करें। जब कोई रिपोर्ट करे “यह लिस्ट गलत लग रही है”, तो ये logs बग को सुलझाने योग्य बनाते हैं।
सरल TTLs से शुरू करें, फिर उपयोगकर्ताओं की रिपोर्ट के आधार पर refine करें। एक न्यूज फ़ीड 5–10 मिनट की staleness सहन कर सकता है, जबकि ऑर्डर स्टेटस स्क्रीन को resume पर और किसी भी checkout एक्शन के बाद रिफ्रेश चाहिए।
अगर आप जल्दी Flutter ऐप बना रहे हैं, तो किसी भी implementation से पहले अपनी डेटा लेयर और cache नियम का खाका बनाना मददगार होता है। Koder.ai (koder.ai) का उपयोग करने वाली टीमों के लिए, planning mode में per-screen नियम लिखना एक व्यावहारिक जगह है ताकि बाद में बिल्ड उनसे मेल खाए।
जब आप refresh व्यवहार tune कर रहे हों, तो स्थिर स्क्रीन की रक्षा करें जबकि आप प्रयोग करते हैं। Snapshots और rollback बचाने में मदद कर सकते हैं जब कोई नया नियम अनजाने में flicker, खाली स्टेट, या नेविगेशन के दौरान inconsistent counts ला दे।
Start with one clear rule per screen: what it may show immediately (cached), when it must refresh, and what the user sees during refresh. If you can’t explain the rule in one sentence, the app will eventually feel inconsistent.
Cached data को एक freshness state मानें। अगर यह ताज़ा है तो दिखाएँ। अगर यह स्टेल पर उपयोगी है तो तुरंत दिखाएँ और पृष्ठभूमि में quietly refresh करें। अगर यह मस्ट-रिफ्रेश है तो दिखाने से पहले सर्वर से डेटा लें या लोडिंग/ऑफ़लाइन स्टेट दिखाएँ। यह UI व्यवहार को हर बार एक जैसा रखता है।
बहुत पढ़ी जाने वाली और धीरे-धीरे बदलने वाली चीज़ें कैश के लिए अच्छी होती हैं: फीड, कैटलॉग, संदर्भ डेटा और बेसिक प्रोफ़ाइल जानकारी। पैसे या समय-संवेदी डेटा (बैलेंस, स्टॉक, ETA आदि) जोखिमभरा है — उन्हें स्पीड के लिए कैश किया जा सकता है पर निर्णय से ठीक पहले हमेशा रिफ्रेश करें।
सत्र के भीतर तेज़ reuse के लिए memory; रीस्टार्ट्स के बाद बने रहने वाले छोटे आइटमों के लिए disk key-value; बड़े, संरचित या ऑफ़लाइन-फ़्रेंडली डेटा के लिए लोकल database।
एक साधारण TTL अच्छा डिफ़ॉल्ट है: डेटा को कुछ समय के लिए ताज़ा मानो, फिर रिफ्रेश करो। लेकिन बेहतर UX के लिए अक्सर “show cached now, refresh in background, update if changed” पैटर्न काम करता है — खाली स्क्रीन और flicker कम होता है।
वे घटनाएँ जिन्हें cache की विश्वसनीयता कम कर देती हैं: यूज़र edits (create/update/delete), login/logout या अकाउंट बदलना, ऐप resume अगर डेटा TTL से पुराना है, और यूज़र द्वारा explicit refresh. इन triggers को छोटा और स्पष्ट रखें।
दोनों स्क्रीन एक ही source of truth पढ़ें, निजी कॉपियाँ न रखें। जब यूज़र details में कुछ बदलता है, shared cache ऑब्जेक्ट तुरंत अपडेट करें ताकि list स्क्रीन पर वापस जाने पर नया वैल्यू दिखे।
हर cached payload के साथ metadata रखें, खासकर timestamp और user identifier. लॉगआउट या अकाउंट स्विच पर user-scoped cache एंट्रीज़ तुरंत साफ़ या अलग करें और पुराने यूज़र से जुड़ी in-flight requests cancel करें।
स्टैंडर्ड व्यवहार: stale डेटा को दिखाते रहें और एक छोटा, स्पष्ट error दिखाएँ जो retry ऑफर करे। ब्लैंक स्क्रीन दिखाने की बजाय cached डेटा रखें; अगर स्क्रीन पर पुराना डेटा दिखाना खतरनाक है तो उसे must-refresh बनाओ और लोडिंग/ऑफ़लाइन संदेश दिखाओ।
Cache नियम और तर्क डेटा लेयर (repositories) में रखें ताकि हर स्क्रीन एक जैसा व्यवहार करे। Koder.ai उपयोग कर रहे teams के लिए: पहले per-screen freshness और invalidation नियम Planning Mode में लिखें, फिर implementation में UI सिर्फ state पर प्रतिक्रिया करे।