**Parallelize**: use `multiprocessing.Pool` or `concurrent.futures.ProcessPoolExecutor` to generate reports in parallel. A 1000-customer job that takes 1 hour sequentially can finish in 10 minutes on a 16-core machine. - **Batch data loading**: load all customers' data once rather than once per repo