惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 司徒正美
T
The Blog of Author Tim Ferriss
雷峰网
雷峰网
S
Secure Thoughts
GbyAI
GbyAI
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
G
GRAHAM CLULEY
MongoDB | Blog
MongoDB | Blog
WordPress大学
WordPress大学
M
MIT News - Artificial intelligence
Martin Fowler
Martin Fowler
C
Cyber Attacks, Cyber Crime and Cyber Security
I
Intezer
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
T
Threatpost
S
Securelist
T
Tenable Blog
博客园_首页
P
Privacy International News Feed
Cisco Talos Blog
Cisco Talos Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
C
CXSECURITY Database RSS Feed - CXSecurity.com
小众软件
小众软件
美团技术团队
Project Zero
Project Zero
The Cloudflare Blog
L
Lohrmann on Cybersecurity
The Register - Security
The Register - Security
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LINUX DO - 热门话题
C
CERT Recently Published Vulnerability Notes
C
Cybersecurity and Infrastructure Security Agency CISA
有赞技术团队
有赞技术团队
IT之家
IT之家
A
Arctic Wolf
Scott Helme
Scott Helme
Latest news
Latest news
T
Tailwind CSS Blog
Jina AI
Jina AI
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
Cyberwarzone
Cyberwarzone
宝玉的分享
宝玉的分享
The Hacker News
The Hacker News
S
Schneier on Security
Y
Y Combinator Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
How to keep your OTA updates lean and fast
Dan · 2026-05-18 · via DEV Community

Originally published on expo.dev/blog by Jacob Clausen.


Have you ever shipped a critical fix to your entire user base within minutes of merging the PR - a straight highway from your fix to your users’ fingertips, no bureaucracy, no interruption to the user experience? That feeling never gets old.

EAS Update makes this possible, and once you’ve experienced it, it’s hard to imagine working without it. But publishing the fix is only half the story. Your users don’t benefit until it’s running on their devices. The faster that download completes, the sooner your fix is in their hands. And the leaner your updates are, the better the experience gets for everyone. Faster downloads, lower costs, and a smoother ride as your team and user base grow. In this guide, we’ll walk through how to keep your updates small, ship them with confidence, and get the most out of every push.

EAS Update pricing recap

To get the most out of EAS Update, it helps to understand two concepts that shape how your updates are delivered and billed: Monthly Active Users (MAUs) and bandwidth. Knowing how they work, and the things you can do to keep your updates lean, means faster downloads for your users and lower costs for you. This blog post assumes you’re already familiar with what EAS Update is and what scenarios it’s useful for.

Monthly Active Users (MAUs)

A Monthly Active User (MAU) is a unique user who downloads at least one update via EAS Update within a single billing period. No matter how many updates they download that month, they still count as one MAU. And if a user checks for updates but nothing new is available (so no download happens), they’re not counted at all.

Uninstalling and reinstalling the app will count as a separate MAU the next time they download an update. Similarly, the same person on two different devices would count as two MAUs. These edge cases probably won’t dramatically change your numbers, but they’re good to be aware of if your actual MAU count doesn't exactly match Play and App Store counts or metrics that consider more context about the unique identities of your users.

Bandwidth

While every update a user downloads consumes bandwidth, the quotas on each plan are generous, and most teams stay comfortably within their plan's allocation. Actual bandwidth usage tends to be much lower than you might expect, thanks to factors like compression.

The size of that download depends on what changed. For example, if only your JavaScript was updated, that’s all the user downloads. Assets already on the device from the original build (or from a previous update) aren’t re-downloaded.

That number is often smaller than you’d think: if you publish three updates in a week and a user only opens your app once that week, they download one update - not three. Only the latest update is downloaded, and the rest are skipped. From both a speed and bandwidth perspective, this is great - your users aren’t downloading more than they need to, which means updates are delivered faster and you’re only paying for what’s actually being used.

That said, keeping your updates lean is still worth doing for a bunch of reasons beyond billing: faster downloads, less data usage for your users, and a snappier experience all around. More about this later.

One thing we’re really excited about: with SDK 55, you can opt in to Hermes bytecode diffing (currently in beta, please check it out!). Instead of downloading a full JavaScript bundle, the client applies a binary diff to what’s already installed. This can reduce download sizes significantly, meaning your users get updates faster and you can ship more frequently. It’s one of the ways we’re actively working to make updates both cheaper to deliver and better for your users.

Why smaller updates matter

The smaller your updates are, the faster they download for your users - and the less bandwidth each update consumes, both for your EAS Update usage and for your users on cellular or limited data plans. Smaller bundles also mean faster builds, and when your app loads an update on launch, a leaner bundle means a snappier startup. And if your bundle gets large enough, you might even notice it during development - live reload can start to feel slow when it has to process a big bundle on every change. Here are some techniques worth knowing about.

Optimize your assets

Images can add up quickly in your update size, so it’s worth making sure they're optimized before you ship. Compressing your images where possible can make a meaningful difference - often with little to no visible quality loss. The smaller your images, the faster your updates download and the less data your users consume.

Let your assets be assets

When an image is a proper asset file, it gets downloaded once (either through a build or an update) and stays on the device. Future updates skip it entirely if it hasn’t changed. But when assets are inlined in your JavaScript (like for example base64-encoded images), they’re part of the bundle itself, so they come along for the ride on every update.

For images that change frequently or live outside your bundle entirely, serving them from a CDN paired with expo-image is worth considering. Its default caching policy persists images to disk on first load, so they behave just like bundled assets after that (downloaded once, reused across app restarts) without adding any weight to your updates.

Choose which assets go into your updates

Not every asset in your project needs to be delivered through updates. With asset selection, you can specify exactly which assets should be included using file patterns in your app config. Everything else stays in the native build and never gets downloaded from the update server.

For example, if only the images in your app/images directory change between releases, you can limit your updates to just those:

{
  "expo": {
    "updates": {
      "assetPatternsToBeBundled": [
        "app/images/**/*.png"
      ]
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Once you’ve configured your patterns, run npx expo-updates assets:verify before publishing. This ensures that all required assets will be included when you publish an update - assets that fall through the cracks won't be available, which can cause unexpected behavior or crashes. Check out the docs for more details.

Submit to the app stores regularly

When you submit a new build to the app stores, it includes all your latest assets. That means any OTA updates you publish after that only need to include what’s changed since the build, so users download less. If you’ve recently added large or multiple new assets, shipping a new build is a good way to keep your next updates lean.

One approach that works well is pairing a regular binary release cadence (say, monthly) with OTA updates for changes in between. Your users get improvements more frequently, and each new binary resets the asset baseline for your subsequent updates.

Keep your JavaScript bundle in check

OTA Update optimization

Your JavaScript bundle is part of every update you publish. Tools like Expo Atlas give you a visual breakdown of your bundle, showing exactly how much space each dependency takes up. It can be a real eye-opener - you might discover a library you imported for a single utility function is pulling in way more than you expected, or spot a dependency you stopped using but never removed.

You can try it right now with your local dev server. Start your app with Atlas enabled:

EXPO_ATLAS=true npx expo start

Then press shift + m in the terminal running the dev server to open the dev tools plugin menu and launch Atlas.

Shipping updates efficiently

So far we’ve covered how to keep your updates lean. But the way you ship updates matters too. Rollouts give you more control over how updates reach your users, and using updates for internal testing can save you time and build credits.

Use rollouts for production updates

When you publish an update, it’s available to your entire user base by default. Every update your users download counts toward your bandwidth usage, so rollouts are a natural way to be efficient: start with a small group, make sure everything looks good, and then roll it out to everyone.

Use updates for internal testing and PR previews

During development, getting changes in front of your team for review often means creating a new build. But for changes that don’t involve native code, an OTA update does the same job - and it takes only seconds. Your team can preview changes directly on a development build they already have installed, or even from a pull request preview that’s generated automatically.

The more of your review and iteration cycle that happens through updates rather than builds, the less time you spend waiting around before anyone can look at a change. Your team can have the latest version on their device in seconds, which means the feedback loop opens up much earlier in the process. That adds up fast when you’re iterating on a feature, and you’re saving build credits along the way. And since it’s just your team downloading these updates, the MAU and bandwidth cost is practically zero, making it one of the best value-for-effort wins on your plan.

Keeping track of your usage

Everything we’ve covered so far (keeping updates lean, using rollouts, leveraging updates for internal testing) all contributes to getting more value out of your EAS Update plan. But it’s also nice to know where you can see how things are going.

Monitor your usage in the dashboard

Expo provides a usage overview on your account’s Billing and Usage pages. There you’ll find a summary of your EAS Update usage: how many MAUs have downloaded updates and how much bandwidth has been consumed during the current billing cycle (or given time period). It’s a handy way to stay informed, especially if you’re curious how your numbers look after a big release.

Use the pricing calculator to find the right plan

If you’re trying to figure out which subscription plan fits your needs, the pricing calculator on the Expo website can help. Adjust the sliders for your expected MAU count, builds, and CI/CD minutes, and it’ll recommend a plan - and if your numbers go beyond what’s included in that plan, it’ll show you the estimated cost of that extra usage too.

Pick the plan that fits today

You don’t need to have everything figured out before choosing a plan. Start with what fits your current needs - you won’t hit a wall if your app grows faster than expected. Every plan scales naturally with your usage, and you can move between plans as your needs change. Expo’s pricing is designed to grow with you, not get in the way. EAS Update is available on every plan, including the free plan, so you can try it out without any commitment.

Wrap-up

At the end of the day, EAS Update gives you a pretty sweet deal: ship updates to your users in seconds, iterate faster with your team, and scale at your own pace. Leaner updates, rollouts, and a few of the techniques we covered are all it takes to deliver a faster experience for your users while getting more value out of your plan.

Ready to get started? Set up EAS Update in your project - it only takes a few minutes to set up, and you can start shipping updates right away. If you want to dive deeper into any of the topics we covered, the EAS Update docs are a great next step. We’d love to hear about your success story with EAS Update too!