So it turns out you can't cache using VaryByParm and dynamic parameters

Thankfully there is a way to achieve the outcome we needed (cached sublayouts varied by the catery/subcatery of the site) with little change to the application. Instead of using the <sc:Sublayout /> control we created a new Sublayout that overwrites the GetCacheKey() method to add _#itemId:. This means the parameters are no longer dynamic and we can retrieve and display the cached content. public class Sublayout : Sc.Web.UI.WebControls.Sublayout { public override string GetCacheKey() { var site = Sc.Context.Site; if ((Cacheable && ((site == null) || site.CacheHtml)) && !SkipCaching()) { if (VaryByParm) { return base.GetCacheKey() + "_#itemId:" + Sc.Context.Item.ID; } return base.GetCacheKey(); } return string.Empty; } }