Have a look at :binary.match/2 and :binary.compile_pattern/1. If the list changes infrequently (relative to the frequency of matches) you’ll benefit greatly from a compiled pattern.
There was some discussion in various places about VM optimizations recently, e.g.:
Instead of storing that 20k strings in list create trie. It will give You much better complexity. Or you can build just big NFA like BurntSushi’s fst Rust library, there you have detailed blog post about it. Using Flow or Stream will only hide the complexity instead of solving it.