Melt the butter in your pot over medium heat, then add the chopped onion and celery. Cook for about 4-5 minutes, stirring occasionally, until they turn soft and fragrant. This step builds the flavor foundation for the entire soup, so don't rush past it.
Sprinkle the flour directly over the softened onions and celery, stirring constantly for about a minute. This cooks off the raw flour taste and creates a paste that will thicken your soup later. Keep the heat at medium so nothing browns too quickly.
Slowly pour in the broth while whisking, so the flour blends smoothly instead of forming lumps. Add your diced potatoes, salt, pepper, and paprika, then bring everything to a gentle boil before reducing the heat.
Let the soup simmer uncovered for about 15-18 minutes, stirring occasionally, until the potatoes turn fork-tender. This is also when I like to check the seasoning and adjust it slightly before moving forward.
Use a potato masher to break down some of the potatoes right in the pot. I usually mash about half of them, which naturally thickens the soup while still leaving satisfying chunks throughout.
Pour in the milk and stir gently, letting the soup return to a light simmer. Avoid boiling it hard at this stage, since high heat can cause the dairy to separate or curdle.
Reduce the heat to low, then add the shredded cheddar cheese in small handfuls, stirring after each addition until fully melted. Adding it gradually on low heat keeps the texture smooth and prevents the cheese from turning grainy.
Ladle the soup into bowls immediately while it's warm and creamy. Top it with a little extra cheese and chopped chives if you like a fresh, sharp finish.