Peel and dice potatoes into small cubes. Chop onion and mince garlic.
In a large pot, melt butter over medium heat. Add onion and garlic and cook for 3 to 4 minutes until softened and fragrant.
Stir in flour and cook for about 1 minute, stirring constantly to form a roux.
Pour in broth and add diced potatoes. Stir and bring to a gentle boil.
Reduce heat and simmer for 15 to 20 minutes until potatoes are fork-tender.
Use an immersion blender to blend the soup until smooth, or blend partially for a chunkier texture.
Stir in milk and heavy cream. Simmer on low heat for 5 to 10 minutes without boiling.
Season with salt and black pepper to taste.
Serve warm with optional toppings like bacon, cheese, or herbs.