In a medium saucepan, whisk together the milk, heavy cream, sugar, cornstarch, and salt until smooth and fully combined.
Place over medium heat and cook, whisking constantly, until the mixture thickens and begins to bubble, about 6 to 8 minutes.
Once thickened, continue cooking for 1 additional minute to fully activate the cornstarch.
Remove from heat. In a separate bowl, whisk the egg yolks. Slowly ladle about ½ cup of the hot mixture into the yolks, whisking constantly to temper.
Pour the tempered egg mixture back into the saucepan, whisking continuously.
Return to low heat and cook for 1 to 2 minutes, stirring constantly, until smooth and thickened.
Remove from heat and stir in the butter until melted and fully incorporated.
Add the lemon zest, lemon juice, and vanilla extract. Stir until smooth.
Strain the pudding through a fine mesh sieve into a clean bowl for the smoothest texture.
Cover with plastic wrap, pressing it directly onto the surface to prevent a skin from forming.
Refrigerate for at least 2 hours, or until fully chilled and set.