Design your mobile application for low bandwidth Networks
Why?
Optimizing mobile application performance for low bandwidth networks is an absolute need in India, given the fluctuations in network speed
Performance can be a deal breaker for mobile applications and the impact of performance gets magnified several times on low bandwidth networks. In India roughly 50% of network traffic is 2G (direct or degraded speed) and some of the Tier II and III cities have coverage only for 2G. For any realtime commerce App, the impact of performance to discovery and conversion can be staggering.
The funnel drop off % for mobile app launches on low bandwidth networks can be mind boggling. If you are a Product or Engineering manager managing mobile experiences, you may want to check the following insights right away and you may be either shocked or surprised!
- How many users tried to launch the app
- What % of users actually were able to make it to discovery experience
- Distribution of drop offs by network speed (2G, 3G, wi-fi)
- Distribution of drop offs by carrier type
In this post I will share my past experience on how I approached this from diverse perspectives and I hope it will help you.
First Things First
Performance optimisation is going to be a long journey and it is not an one time effort. You need a good start backed by data and validation to get attention from Business and create enough impetus to sustain it.
I would recommend to start with launch experience, no guesses as it the start of the funnel and any drop offs here is clearly a lost opportunity for the Business.
Clearly establish a success metric (example: reduction in bounce rate during launch) and set yourself an audacious goal (example: reduce the launch time by 10X on low bandwidth networks) and deliver to promise.
The Crux
Prioritise and apply relevant best practices to optimise mobile application performance. I have taken some of the most common recommendations and have given it a layman’s spin below to make it interesting and more importantly to make it stick.
Be Frugal
Make just enough network calls - network calls are expensive, especially on low bandwidth networks
Batch outbound requests to logical grouping (realtime sensitiveness vs tolerance to stale)
- Batch instrumentation related requests and ensured that the batch size and intervals are optimised based on network type
Tune the batch update intervals and batch size optimally for all 3rd party SDKs if and as applicable
Remove redundant/unnecessary calls
- Common mistakes teams make could be unintentionally using two different SDKs with overlapping functions. example: crash reporting
Remove redirects
Use just enough payload
Minify payload
- Deeply inspect headers, params, payload for each request and response and minify every thing is possible
Compress payload
- Compression can give you significant savings in network bandwidth and surprising improvements in end to end latency
- You may want explore other alternatives like binary json.
Optimize Images
- Use image optimisation tools to compress images
- Use adaptive resolution pattern to fetch rightly sized images based on device resolution
Use just enough resource
Battery
- Wake locks drain battery and enable wake locks only on demand
Memory, CPU
- Profile your application, identify and optimize Memory/CPU hoggers
Location
- For seamless perceived user experience, piggyback on OS last known location during start until the first location fix is obtained
Just enough features
Based on the network speed, explore the possibility of turning on only must required features
When does matter!
Setting your priorities
Pre fetch high priority/context sensitive information first
- Trigger the most important network calls as early as you can, so that the landing experience for the user has realtime data for call to action
- Use HTTPPriorityQueue and assign priority accordingly for each HTTP Request
Defer and distribute fetching of less priority info
- Defer the initialisation of non essential SDKs by delegating to a low priority thread. This can lead to significant improvements and most SDK init() make network calls and if they are sequential it can lead to significant delays
- Cache the time series data in memory to retain the data points till the loading of SDK is completed
Saving is an art
Cache a lot when times are good (on a good network)
- On wi-fi cache less frequently changing resources aggressively
- Use cache-control paradigm for less frequently changing resources by using a HEAD call or equivalent for other protocols to lookup for changes
Cache incrementally always
Cache only what is required and let go (weak references) when times are bad (memory utilisation)
- Explore caching at memory (LRU) and disk based on the need for faster lookup and tolerance to staleness
Order matters
Be wary of blocking calls in critical path
- Remove all blocking calls at launch, triggered critical calls as high priority threads, non critical calls as low priority threads leading huge improvements
Pick your battles on Async vs Sync calls
- Trigger calls on critical path as Async and implement the observer pattern to ensure all calls converge at the finish point
Less is more
Get more with less
Aggregate multiple InBound responses to a single API response
- Establishing network connection on low bandwidth network is very costly and aggregating the responses at the server side can help. This may not be one size fits all and one need to diligently balance between the response size, processing time for individual responses and customer experience
Get only when needed
Minimize poll
- Using adaptive fetch (server controlled depending on load) instead of fixed interval fetch which is
- Push can be major winner here and one should look beyond HTTP
Fail (course correct) fast
Release resources quickly
Implement circuit breakers for connections, GPS locks, timers etc
- When frequent low latency refresh calls are made, cancel all older calls which were stuck due to network delays
Implement fallback offline/online experience as applicable
All that not(!) Jazz
Performance can be a great experience by itself!
- Simplicity may != kick ass graphics and animation
Getting the attention
Though improving performance is something everyone would agree to, prioritising such a large tech driven initiative into the product roadmap is not trivial. Hence you should create a quick win (a working prototype always works wonders than mere theory) and demonstrate it to the stakeholders. This is critical to get attention and get the effort prioritized.
Structure Drives Behaviour
Since multiple teams will be involved, put together a clear structure on the goals, metrics, teams, timelines and prioritise the effort into the release sprints.
To ensure that your team internalise this and apply it consistently
- Create a framework (bunch of guiding principles on performance) for the Engineers to internalise, refactor/redesign, iterate, improvise and deliver results.
- Create a mindset to question assumptions on every operation on the critical path
The human side of things
“When you inspire a team to own their creation, half the battle is won”
- Try creating separate teams to avoid any distractions and set clear priority and expectations
- Setup daily stand ups to ensure the team does not take eyes off the goals
- Create positive reinforcements for every incremental improvement
- Catch people doing things right more often
- Create show and tell sessions across functions and levels to provide a platform for the team members to feel proud about what they are doing
- Create a brand for the initiative and spread the word across the floor
- Recognize and reward fairly and consistently
Closing thoughts
Everything mentioned in this blog has already been written in some form or the other and it is not a rocket science. But applying these principles with structure and focus helped me personally and it may just help you.
My heartfelt thanks to Abhilash Ramakrishna, Phaneesh Nagaraja, Abhinash Karan and Ganesh Subramanian for their valuable inputs and contribution.