Preheat oven to 350ºF and grease a 9x13" baking dish with butter or olive oil.
Melt 4 tbsp butter in a large skillet over medium heat.
Add onion and cook, stirring occasionally, for 4-5 minutes until translucent.
Add garlic and cook for another minute until garlic is fragrant.
Sprinkle in flour and cook, stirring, for 1 minute.
Slowly whisk in the milk and cook until sauce is thick and bubbly, about 4-5 minutes.
Add salt, pepper, and cheese and stir until cheese is melted. Remove sauce from heat.
Place half the sliced potatoes in bottom of the baking dish.
Top with half the ham (optional), then pour on half the sauce.
Repeat with the other half of the potatoes, ham, and sauce.
Cover the dish tightly with aluminum foil and bake covered for 45 minutes, then remove foil and bake for another 20-30 minutes until potatoes are tender and top is golden and bubbly. Let cool 10-15 minutes before serving.