Quota และ persistent storage
browser ให้ storage คุณเท่าไหร่?
หัวข้อที่มีชื่อว่า “browser ให้ storage คุณเท่าไหร่?”browser ไม่ได้ให้ storage ไม่จำกัดแก่ทุก origin แต่จะจัดสรร quota ที่เป็นจำนวนสูงสุดที่ origin อาจใช้ โดยพิจารณาจาก disk ที่มีอยู่และนโยบาย browser quota สำหรับ IndexedDB, Cache API และ OPFS มาจาก shared pool ที่เรียกว่า “default” storage bucket
navigator.storage.estimate() API คืนค่า snapshot ของปริมาณ quota ที่ origin ของคุณใช้ไปแล้ว
const { quota, usage } = await navigator.storage.estimate();console.log('Quota :', (quota / 1024 / 1024).toFixed(1), 'MB');console.log('Usage :', (usage / 1024 / 1024).toFixed(2), 'MB');ค่า usage ที่คืนมาครอบคลุม IndexedDB, Cache API และ OPFS รวมกัน ไม่รวม localStorage หรือ cookies ซึ่งมี limits แยกต่างหากที่เล็กกว่า
Best-effort กับ persistent storage
หัวข้อที่มีชื่อว่า “Best-effort กับ persistent storage”โดยค่าเริ่มต้น ทุก origin จะได้รับ best-effort storage ภายใต้ disk ที่มีน้อย browser มีอิสระที่จะ evict ข้อมูล best-effort ได้ โดยไม่มีการแจ้งเตือน เพื่อเพิ่มพื้นที่ ลำดับการ evict มักเป็น origin ที่ใช้งานล่าสุดน้อยที่สุดก่อน
คุณสามารถขอให้ browser อัปเกรด origin ของคุณเป็น persistent storage ข้อมูล persistent จะไม่ถูก evict โดยไม่มีการกระทำที่ชัดเจนจากผู้ใช้ (การล้าง site data) ในการขอ:
const granted = await navigator.storage.persist();console.log('Persistent storage granted:', granted); // true หรือ falseในการตรวจสอบสถานะปัจจุบันโดยไม่ขอ:
const isPersisted = await navigator.storage.persisted();console.log('Already persistent:', isPersisted);browser จะอนุมัติ persistence เมื่อไหร่?
หัวข้อที่มีชื่อว่า “browser จะอนุมัติ persistence เมื่อไหร่?”browser ใช้ engagement heuristics ในการตัดสินใจว่าจะอนุมัติ request แบบเงียบ ๆ หรือแสดง permission prompt ปัจจัยที่เพิ่มโอกาสในการได้รับการอนุมัติโดยอัตโนมัติ ได้แก่:
- Site ถูก install เป็น PWA (เพิ่มใน Home Screen / ติดตั้งผ่าน browser UI)
- ผู้ใช้เยี่ยมชม site บ่อยครั้ง
- ผู้ใช้ bookmark site หรือมอบ permissions อื่น ๆ (push notifications, geolocation)
- บาง browser (Firefox) จะถามผู้ใช้เสมอ browser ที่ใช้ Chromium อาจอนุมัติเงียบ ๆ
storage durability สองระดับ
หัวข้อที่มีชื่อว่า “storage durability สองระดับ”flowchart TD
A[Origin stores data] --> B{Durability tier}
B -->|Default| C[Best-effort storage]
B -->|After persist granted| D[Persistent storage]
C --> E[Browser MAY evict under\ndisk pressure]
E --> F[Data silently deleted]
D --> G[Browser will NEVER evict\nwithout user action]
G --> H[Data safe until user\nclears site data] Runnable: ตรวจสอบ quota และสถานะ persistence
หัวข้อที่มีชื่อว่า “Runnable: ตรวจสอบ quota และสถานะ persistence”snippet ด้านล่างเรียกทั้ง estimate() และ persisted() และบันทึกผลลัพธ์ ไม่มีการเขียน demo keys ดังนั้นไม่ต้องทำความสะอาด
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Best-effort storage (default) | ไม่ต้องขอ permission จากผู้ใช้ ใช้งานได้ทันที | browser อาจ evict ข้อมูลเงียบ ๆ เมื่อ disk เหลือน้อย |
Persistent storage (persist()) | ข้อมูลปลอดภัยจนกว่าผู้ใช้จะล้าง site data เอง | ต้องพึ่ง engagement heuristics ของ browser ซึ่งควบคุมไม่ได้ทั้งหมด และบาง browser จะแสดง permission prompt ที่ผู้ใช้อาจปฏิเสธ |
เรียก estimate() ก่อนเขียนข้อมูลก้อนใหญ่ | รู้ headroom ที่เหลือ ป้องกัน QuotaExceededError กลางทาง | เพิ่ม async round-trip หนึ่งครั้งก่อนเริ่ม operation จริง |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- คิดว่า IndexedDB เท่ากับ “เก็บถาวรตลอดไป” — โดย default ทุก origin ได้แค่ best-effort storage เท่านั้น ต้องเรียก
navigator.storage.persist()เพื่อขออัปเกรดเป็น persistent จริง ๆ - ไม่เช็ก quota ก่อนเขียนข้อมูลก้อนใหญ่ — เขียนไปเรื่อย ๆ โดยไม่เรียก
navigator.storage.estimate()ก่อน ทำให้เจอQuotaExceededErrorแบบไม่ทันตั้งตัวเมื่อ disk เหลือน้อย - สับสนระหว่าง
usageที่ได้จากestimate()กับlocalStorage— ค่าที่คืนมาครอบคลุมแค่ IndexedDB, Cache API และ OPFS เท่านั้น ไม่รวมlocalStorageหรือ cookies ซึ่งมี limit แยกต่างหาก
💡 ตัวอย่างจากของจริง
Google Photos — เรียก
navigator.storage.persist()หลังผู้ใช้ install เป็น PWA เพื่อให้ cached thumbnails และ offline queue ไม่ถูก evict ระหว่างใช้งานแบบ offlineNotion / Google Docs offline mode — เช็ก
navigator.storage.estimate()ก่อน sync document ขนาดใหญ่ลง IndexedDB เพื่อเตือนผู้ใช้ล่วงหน้าเมื่อ quota ใกล้เต็ม แทนที่จะปล่อยให้ sync ล้มเหลวกลางทาง