Preheat and prep. Heat the oven to 375°F (190°C). Grease a 9x13-inch baking dish with butter or oil. If your oven runs cool, go to 400°F for a crisper top.
Slice the potatoes and onion. Aim for 1/8-inch potato slices so they cook evenly.
A mandoline helps, but a sharp knife works fine.
Make the cheese sauce base. In a saucepan, melt 4 tablespoons butter over medium heat. Stir in the flour and cook 1–2 minutes, whisking, until it smells nutty but not browned.
Add liquids. Slowly whisk in the milk and broth. Keep whisking until smooth and slightly thickened, 3–5 minutes.
Season and enrich. Stir in garlic, Dijon, smoked paprika, black pepper, and a small pinch of salt.
Simmer 1 minute. Off the heat, stir in sour cream (if using), 1 1/2 cups cheddar, and 1/4 cup Parmesan until melted.
Layer the casserole. Add half the potatoes to the dish in an even layer. Top with half the onions and half the diced ham.
Spoon over half the cheese sauce. Repeat with remaining potatoes, onions, ham, and sauce.
Finish with cheese. Sprinkle the remaining 1/2 cup cheddar and 1/4 cup Parmesan over the top. Add a pinch of thyme or parsley if you like.
Bake covered, then uncovered. Cover tightly with foil and bake 35–40 minutes.
Remove foil and bake another 20–25 minutes, until bubbly and the potatoes are tender when pierced with a knife.
Rest before serving. Let it sit 10–15 minutes so it sets and slices cleanly. Garnish with more herbs if you want a fresh pop.