diff --git a/cmd/redirectord/redirectord.go b/cmd/redirectord/redirectord.go
index bb1cd8baf5fe5b9837545540e7114793f22210a5..92ed0e29d07c4154ee8333f0c593c9cd9fc4734e 100644
--- a/cmd/redirectord/redirectord.go
+++ b/cmd/redirectord/redirectord.go
@@ -18,7 +18,7 @@ var (
 	httpPort    = flag.Int("http-port", 80, "HTTP port")
 	staticDir   = flag.String("static-dir", "/usr/share/autoradio/htdocs/static", "Static content directory")
 	templateDir = flag.String("template-dir", "/usr/share/autoradio/htdocs/templates", "HTML templates directory")
-	lbPolicy    = flag.String("lb-policy", "weighted", "Load balancing policy (weighted, leastloaded)")
+	lbPolicy    = flag.String("lb-policy", "listeners_available,listeners_score,weighted", "Load balancing rules specification (see godoc documentation for details)")
 
 	// Default DNS TTL (seconds).
 	dnsTtl = 5
diff --git a/fe/loadbalancing.go b/fe/loadbalancing.go
index bdcc041250c3883abec37f1c6d29ae597f341cde..d4d49e21d7237772225291bad11ea28c988158c6 100644
--- a/fe/loadbalancing.go
+++ b/fe/loadbalancing.go
@@ -1,6 +1,7 @@
 package fe
 
 import (
+	"errors"
 	"fmt"
 	"net"
 	"strings"
@@ -108,32 +109,45 @@ func (l *autoradioLoadBalancer) Choose(ctx lbv2.RequestContext) *autoradio.NodeS
 	return result.(*lbNode).NodeStatus
 }
 
+// Parse a string that specifies how to build a LoadBalancer. The
+// string should consist of a list of comma-separated tokens, each
+// identifying a specific filter or policy.
+//
+// Some filters will always be included in the resulting LoadBalancer
+// and do not need to be specified explicitly (icecastActiveFilter and
+// ipProtocolFilter, plus an activeNodesFilter at the end).
 func parseLoadBalancerSpec(specstr string) (*autoradioLoadBalancer, error) {
 	lb := lbv2.New()
 	lb.AddFilter(newIcecastActiveFilter())
 	lb.AddFilter(newIpProtocolFilter())
 
+	var policy lbv2.Policy
 	for _, spec := range strings.Split(specstr, ",") {
 		switch spec {
-		case "ba", "bw_avail", "bandwidth_available":
+		case "bandwidth_available":
 			lb.AddFilter(lbv2.NewCapacityAvailableFilter(lb.GetPredictor(UTIL_BANDWIDTH)))
-		case "la", "listeners_available":
+		case "listeners_available":
 			lb.AddFilter(lbv2.NewCapacityAvailableFilter(lb.GetPredictor(UTIL_LISTENERS)))
-		case "bw", "bandwidth_weight":
+		case "bandwidth_score":
 			lb.AddFilter(lbv2.NewCapacityAvailableScorer(lb.GetPredictor(UTIL_BANDWIDTH)))
-		case "lw", "listeners_weight":
+		case "listeners_score":
 			lb.AddFilter(lbv2.NewCapacityAvailableScorer(lb.GetPredictor(UTIL_LISTENERS)))
 		case "random":
-			lb.SetPolicy(lbv2.RandomPolicy)
+			policy = lbv2.RandomPolicy
 		case "weighted":
-			lb.SetPolicy(lbv2.WeightedPolicy)
+			policy = lbv2.WeightedPolicy
 		case "best":
-			lb.SetPolicy(lbv2.HighestScorePolicy)
+			policy = lbv2.HighestScorePolicy
 		default:
 			return nil, fmt.Errorf("unknown lb filter spec \"%s\"", spec)
 		}
 	}
 
+	if policy == nil {
+		return nil, errors.New("no lb policy specified")
+	}
+	lb.SetPolicy(policy)
+
 	lb.AddFilter(lbv2.NewActiveNodesFilter())
 
 	return &autoradioLoadBalancer{lb}, nil
diff --git a/fe/loadbalancing_test.go b/fe/loadbalancing_test.go
index 23f5029a11698cb5618af62a8d5de2d3647cee07..e2d8d89e0b28ef63f35dea3ff11491285a6d0a84 100644
--- a/fe/loadbalancing_test.go
+++ b/fe/loadbalancing_test.go
@@ -104,13 +104,13 @@ func TestLoadBalancer_Policies(t *testing.T) {
 	}
 
 	// Weighted should return node1 4 times as often as node2.
-	runLBTest(t, nodes, nil, "bw,weighted", 1000, map[string]int{"node1": 200, "node2": 800})
+	runLBTest(t, nodes, nil, "bandwidth_score,weighted", 1000, map[string]int{"node1": 200, "node2": 800})
 
 	// The 'random' policy will ignore the weights.
-	runLBTest(t, nodes, nil, "bw,random", 1000, map[string]int{"node1": 500, "node2": 500})
+	runLBTest(t, nodes, nil, "bandwidth_score,random", 1000, map[string]int{"node1": 500, "node2": 500})
 
 	// The 'best' policy will always return node2.
-	runLBTest(t, nodes, nil, "bw,best", 1000, map[string]int{"node2": 1000})
+	runLBTest(t, nodes, nil, "bandwidth_score,best", 1000, map[string]int{"node2": 1000})
 }
 
 func TestLoadBalancer_PoliciesIgnoreDisabledNodes(t *testing.T) {
@@ -127,7 +127,7 @@ func TestLoadBalancer_PoliciesIgnoreDisabledNodes(t *testing.T) {
 		},
 	}
 
-	for _, spec := range []string{"bw_avail,weighted", "bw_avail,random", "bw_avail,best"} {
+	for _, spec := range []string{"bandwidth_available,weighted", "bandwidth_available,random", "bandwidth_available,best"} {
 		runLBTest(t, nodes, nil, spec, 1000, map[string]int{"node1": 1000})
 	}
 }