Loading…
Reclaiming Terabytes: Optimizing Android image caching with TLRU
GrabNguyen Van Minh
Summary
The Grab Android application relies heavily on dynamically downloaded images managed through Glide's disk cache, which originally enforced a 100 MB limit without evaluating content age. While the 90th percentile of users consistently hit this maximum capacity, users below the threshold retained stale promotional and feature assets indefinitely. To reclaim storage while protecting user experience, engineers extended Glide's existing DiskLruCache implementation into a Time-Aware Least Recently Used (TLRU) cache. The TLRU design pairs standard maximum size limits with Time-To-Live eviction based on last-accessed timestamps, alongside a minimum size safety threshold that preserves essential files for returning users. This hybrid approach enables proactive eviction of outdated content without causing empty-cache performance penalties or increasing backend requests.
Takeaways
- Standard disk LRU caching only evicts items when the storage limit is breached, allowing outdated images to persist indefinitely on devices below the capacity cap.
- The TLRU cache introduces a Time-To-Live threshold that marks an entry as expired whenever (current_time - last_accessed) exceeds the TTL value.
- A minimum cache size threshold acts as a safety floor, preventing the eviction of expired assets if the overall cache size would fall below that baseline.
Related reading
Grab ·
Scaling out Distroless adoption With AI
Grab is transitioning its microservices to Distroless base images to eliminate unnecessary binaries and reduce vulnerability risks, but the migration risks runtime failures from missing shared objects and system utilities. To safely validate container execution in continuous integration without staging dependencies, the team relied on medium tests that run containerized services alongside internal dependencies managed by Testcontainers. Because hundreds of services lacked this test harness, Grab implemented an agentic workflow using Claude Code and Model Context Protocol integrations to inspect repositories, generate test boilerplate, and resolve configuration errors. Once test baselines are established, an automated patch-test-compare pipeline updates Dockerfiles, constructs multi-stage builds for necessary dynamic libraries, and creates draft merge requests for human approval.
Jia Yee ChongGrab ·
The Hugo evolution: Engineering Grab's unified, one-click data ingestion platform with Apache Flink
Grab's self-service data platform, Hugo, faced significant onboarding friction as streaming pipelines expanded across fragmented systems like Kafka Connect, custom Go applications, and Spark. Engineering teams struggled with cross-platform configuration translations and brittle, manual schema mappings that stretched onboarding over several days. To resolve these bottlenecks, Grab modernized the ingestion architecture by introducing a centralized automation layer powered by Apache Flink and Flink CDC. The updated platform dynamically retrieves Protobuf schemas from Confluent Schema Registry and ingests MySQL binlogs directly into queryable Hive tables without intermediate Kafka hops. This shift dropped pipeline onboarding times to roughly six minutes for Kafka and three minutes for MySQL CDC, driving more pipeline adoptions in one year than in the previous five.
Shuguang XiangGrab ·
Agent platform (Part 1): How we help Grab build and run AI agents at scale
Grab scaled its internal AI tooling by transforming the infrastructure behind a single technical support bot into a standardized agent framework named LLM-Kit. The original Go-based bot revealed critical bottlenecks, including the lack of automated evaluation, painful provider migrations, fragmented observability, and excessive production scaffolding overhead. To address these frictions, engineers developed a FastAPI template pre-wired with LangGraph ReAct agents, remote Model Context Protocol servers, and built-in ROUGE, BLEU, and LLM-as-judge evaluation suites. The framework centralizes model access through an OpenAI-compatible GrabGPT Gateway and unifies observability across services, outbound calls, and agent steps using OpenTelemetry. This extracted scaffolding reduced day-one production setup time from two weeks to roughly an hour while supporting hundreds of production agents.
Kendrick TanGrab ·
Migrating Counter Service storage: Design choices and learnings
Grab migrated its Counter Service storage backend from a legacy wide-column database to Aerospike to support real-time anti-fraud windowed aggregations across tens of thousands of queries per second. To decouple storage from the Rust reader service, engineers introduced a storage facade using enum dispatch, avoiding the per-query heap allocations of boxed trait objects. The reader used configuration-driven operating modes to support shadow reads and deterministic traffic splitting without requiring code updates. On the write path, the schema was redesigned to collapse multiple bucket records into a single sorted map per counter, using atomic server-side operations to increment counters and prune expired entries. This data model redesign reduced total record counts and in-memory primary index usage by over an order of magnitude while enabling a zero-downtime transition.
Jia Long Loh