Crisp the bacon: Add chopped bacon to a large pot or Dutch oven over medium heat. Cook, stirring occasionally, until the bacon is browned and crisp, about 7–9 minutes.
Use a slotted spoon to transfer bacon to a plate lined with paper towels. Leave about 2 tablespoons of bacon drippings in the pot. If there’s less, add the butter.
Sauté the aromatics: Add onion to the pot.
Cook until softened and lightly golden, 4–5 minutes. Stir in garlic and cook 30 seconds, just until fragrant.
Make a quick roux: Sprinkle flour over the onions and garlic. Stir constantly for 1 minute to cook off the raw flour taste.
The mixture will look pasty.
Add the broth: Slowly whisk in the chicken broth to avoid lumps. Bring to a gentle simmer. The soup will start to thicken slightly.
Add vegetables and season: Stir in broccoli and shredded carrot.
Add smoked paprika, Dijon, a pinch of salt, black pepper, and red pepper flakes if using. Simmer uncovered for 10–12 minutes, or until the broccoli is tender but not mushy.
Lower the heat and enrich: Reduce heat to low. Stir in the half-and-half (or cream).
Do not let the soup boil from this point on, or the dairy can split.
Melt the cheese: Add 2 cups of cheddar and the Parmesan in small handfuls, stirring after each addition until fully melted and smooth. If the soup seems too thick, splash in a bit more broth. If it’s too thin, let it simmer on low a few minutes to thicken.
Add bacon and adjust: Stir in most of the crispy bacon, saving some for topping.
Taste and adjust salt and pepper. More cheddar will make it richer; more broth will lighten it.
Serve: Ladle into bowls and top with the remaining cheddar and bacon. A crack of black pepper on top is perfect.