Hey everyone!
I just released recompile_buster, a Mix task that analyzes your project’s xref graph to surface the modules whose changes trigger the most transitive recompilation.
If you’ve ever changed one file and watched half your project recompile, this tool helps you figure out why and where to fix it.
I was working on a large Elixir codebase where incremental compilation times kept growing. mix xref graph gives you the raw data, but it’s hard to know where to start when you have hundreds of files. I wanted a tool that would rank the worst offenders and give actionable next steps.
It’s also useful as a CI guard, the --fail-above flag lets you fail the build if the number of problematic files exceeds a threshold, so you can prevent compile-time coupling from silently creeping back in.
Here is an example using it in the plausible analytics codebase:
> mix recompile_buster
Files causing excessive recompilation (sorted by transitive deps, 3 levels):
# | Trans. deps | Recompiles | File
----+-------------+------------+---------------------------------------------
1 | 308 | 1 | lib/plausible/prom_ex.ex
2 | 130 | 1 | lib/plausible_web/tracker.ex
3 | 123 | 2 | lib/plausible/imported.ex
4 | 114 | 1 | lib/plausible/auth/api_key.ex
5 | 112 | 2 | lib/plausible/billing/plan.ex
6 | 109 | 1 | lib/plausible/ingestion/event.ex
7 | 95 | 1 | lib/plausible/props.ex
8 | 93 | 32 | lib/plausible_web/live/auth_context.ex
9 | 90 | 1 | lib/plausible/billing/plans.ex
10 | 88 | 2 | lib/plausible/billing/feature.ex
11 | 88 | 7 | lib/plausible/imported/google_analytics4.ex
12 | 83 | 1 | lib/plausible/stats/imported/base.ex
13 | 77 | 11 | lib/plausible/imported/importer.ex
14 | 71 | 1 | extra/lib/plausible/site/tracker_script_id_cache.ex
15 | 65 | 1 | lib/plausible/stats/sql/expression.ex
16 | 63 | 7 | lib/plausible/imported/csv_importer.ex
17 | 55 | 5 | lib/plausible/imported/site_import.ex
18 | 52 | 4 | extra/lib/plausible/stats/goal/revenue.ex
19 | 50 | 2 | lib/plausible/sites/index.ex
20 | 49 | 7 | lib/plausible/imported/universal_analytics.ex
Problematic files: 36 | Total transitive deps: 2357
To start investigating the most problematic file, run:
mix recompile_buster --explain lib/plausible/prom_ex.ex
> mix recompile_buster --explain lib/plausible/imported/csv_importer.ex
Explain: lib/plausible/imported/csv_importer.ex
===================================
Unique transitive deps (3 levels): 63 | Direct deps: 7 | Recompiles: 7
A) Files that recompile when csv_importer.ex changes (7):
lib/plausible/imported.ex
lib/plausible/imported/import_sources.ex
lib/plausible/imported/site_import.ex
lib/plausible/stats/imported/base.ex
lib/plausible/stats/imported/imported.ex
lib/plausible_web/live/imports_exports_settings.ex
lib/workers/local_import_analytics_cleaner.ex
B) Direct dependencies of csv_importer.ex (63 unique transitive deps):
lib/plausible/imported/site_import.ex (27 transitive deps)
lib/plausible/imported/importer.ex (24 transitive deps)
lib/plausible/s3.ex (14 transitive deps)
lib/workers/local_import_analytics_cleaner.ex (7 transitive deps)
lib/plausible/clickhouse_repo.ex (4 transitive deps)
lib/plausible/repo.ex (4 transitive deps)
lib/plausible/ingest_repo.ex
Every file in (A) will recompile if any of the 63 files in (B) changes.
To fix this, break the compile dependency (A) or reduce the transitive deps (B) by removing direct dependencies with the most nested deps.
To investigate why a specific file is in (A), run:
mix xref graph --source <file> --sink lib/plausible/imported/csv_importer.ex --label compile






















