Halodoc built a pipeline that replaces LeakCanary's on-device notification with an automated triage system: leaks are serialized to disk, uploaded to Dynatrace when the app backgrounds, deduplicated by leak signature, and turned into JIRA tickets. A custom AI skill called android-memoryleak-solver then reasons from first principles (no pattern catalogue) about the reference chain, classifies leaks as library vs app-caused, and for app leaks produces a root-cause analysis plus a full cascade of GitLab merge requests across every affected module in their multi-repo Android codebase, including version catalogue and consumer bumps. Since launch, 59 leaks were flagged, 47 were app leaks, and 36 have been auto-fixed by the skill, cutting process time by about 70% (roughly 20 minutes of machine time per trace vs 60-120+ minutes manually). Manual MR review remains mandatory before anything ships.

23m read timeFrom blogs.halodoc.io
Post cover image
Table of contents
Quick OverviewWhy Memory Leaks are not caught like crashes are caught via Crashlytics?Part 1 — How Do You Get a LeakCanary Trace Off the Device?Part 2 — From Event to TicketPart 3 — The brain of the workflow: the memory-leak-solver skillLimitations of the workflowConclusionReferencesJoin UsAbout HalodocTags

Questions this post answers

How can I get LeakCanary leak traces off the device instead of relying on the on-device notification?

Register a custom LeakCanary EventListener that filters (not replaces) the default listener list, keep showNotifications set to false, and serialize each leak to an append-only local file. Flush that file to a logging platform via HTTP when the app backgrounds, triggered by ProcessLifecycleOwner's ON_PAUSE, using a delete-on-confirmed-success pattern for at-least-once delivery without a retry scheduler. daily.dev surfaces engineering writeups like this for teams building their own leak reporting pipelines.

Why does LeakCanary's heap analysis run in the same process as my app instead of a separate process?

As of LeakCanary 2.14, heap dumps are analyzed via BackgroundThreadHeapAnalyzer, a background thread inside the app's own process, rather than the separate :leakcanary process that older versions used with a dedicated HeapAnalyzerService. This can be confirmed by checking the merged manifest for the absence of an android:process declaration for a heap-analysis service, meaning any callback code runs same-process, same-JVM. engineers tracking LeakCanary internals for custom tooling can follow this kind of detail on daily.dev.

Why do I need to bump the version number instead of republishing the same SNAPSHOT artifact after fixing a library bug in a multi-module Android project?

Because Gradle treats -SNAPSHOT as a changing module and caches its resolution for 24 hours by default, so even with cacheChangingModulesFor overridden to zero seconds locally, other machines or CI agents with warm caches can silently keep building against the stale artifact. Publishing under a brand new version string guarantees there are no stale bytes published under a name that didn't exist before. teams managing multi-module dependency cascades can find practical breakdowns like this on daily.dev.

891 Impressions