I know one can make a wallet that either waits for every block, or waits for a transaction, then immediately forwards that to either a specific address, or randomly from a group of addresses. Or make it wait a few minutes in between checking so you can batch transactions and save on fees. Depending on your use case, you could do this every few hours instead of every minute.
If you don't want to run a Core wallet, you could maybe have some sort of script running on electrum; where you pregenerate (or use a large gap limit) your thousands of addresses. Millions would need some sort of custom implementation as that's not going to work on a core wallet efficiently.