factor out caching