Melt butter in a large pot over medium heat. Add onion and cook until softened, about 5 minutes. Add garlic and cook for 1 minute more.
Stir in flour and cook for 1 minute, creating a roux.
Gradually whisk in chicken broth, ensuring there are no lumps. Bring to a simmer.
Add potatoes, salt, and pepper. Bring to a boil, then reduce heat and simmer for 15-20 minutes, or until potatoes are tender.
Use an immersion blender to partially blend the soup, leaving some chunks for texture. Alternatively, carefully transfer some of the soup to a regular blender, blend, and return it to the pot.
Stir in milk and heavy cream (if using). Heat through, but do not boil.
Serve hot with your favorite toppings, such as shredded cheese, bacon bits, or green onions.
Notes
For a thicker soup, you can add a cornstarch slurry (1 tablespoon cornstarch mixed with 2 tablespoons cold water) in the last few minutes of cooking. Adjust seasonings to taste.