Peel the potatoes and slice them into 1/4-inch rounds, placing them in a bowl of cold water to prevent browning—this keeps them looking fresh and prevents oxidation. Dice the bacon into 1/2-inch pieces and place in a cold skillet over medium heat. As the bacon cooks slowly from a cold start, it will render its fat gradually and crisp evenly, which takes about 8-10 minutes. While the bacon cooks, thinly slice the onions into 1/8-inch rings and grate or chop the cheese. Preheat your oven to 350°F and lightly grease a 9x13 inch baking dish or similar size.
Once the bacon is crispy, transfer it to a paper towel-lined plate, leaving about 2 tablespoons of bacon fat in the skillet. If needed, add the olive oil to reach about 3 tablespoons total fat in the pan. Add the sliced onions and cook over medium-high heat for about 10-12 minutes, stirring occasionally, until they're deeply golden and caramelized. Season with a pinch of salt and pepper as they cook. I like to let the onions get really brown at the edges—this creates deeper, sweeter flavor that elevates the entire dish.
In a separate saucepan, melt the butter over medium heat. Once melted and foaming, whisk in the flour to create a smooth paste (called a roux), stirring constantly for 2 minutes to cook out the raw flour taste. Gradually add the milk while whisking continuously to prevent lumps from forming. Simmer for 2-3 minutes, stirring frequently, until the sauce thickens enough to coat the back of a spoon. Season with 1 teaspoon garlic powder, salt, and pepper to taste. The sauce should be creamy and pourable—if it's too thick, thin it slightly with a splash more milk.
Drain the potatoes from the cold water and pat them dry with paper towels—drying them helps them cook evenly and prevents excess water in the dish. Begin layering in the prepared baking dish: start with half of the potatoes in an even layer on the bottom, then scatter half of the caramelized onions, half of the crispy bacon, and half of the grated cheese over the potatoes. Pour half of the cream sauce from Step 3 evenly over this layer. Repeat with the remaining potatoes, onions, bacon, and cheese, finishing with the final half of the cream sauce poured over the top.
Cover the casserole dish tightly with aluminum foil and place it in the preheated 350°F oven. Bake for 1 hour covered—this allows the potatoes to steam and become tender while the sauce stays creamy. After 1 hour, carefully remove the foil and bake for an additional 30 minutes uncovered, until the top is golden brown and the edges are bubbling. I like to tent the foil loosely for the last 10 minutes of cooking if the top seems to be browning too quickly.
Remove the casserole from the oven and let it rest at room temperature for 10 minutes before serving. This resting period allows the sauce to set slightly, making each portion hold together better when scooped, and gives the flavors a moment to meld together. Serve warm, scooping from the sides and bottom of the dish to ensure everyone gets layers of creamy potatoes, bacon, and cheese.