diff --git a/fe/http.go b/fe/http.go
index 73d8f3924ddbd5067df45948e3be3db4afbd8845..89cd8fceaa58b77551dcc2acf13ecc3ad568770a 100644
--- a/fe/http.go
+++ b/fe/http.go
@@ -316,10 +316,12 @@ func (h *HttpRedirector) createHandler() http.Handler {
 			nil))
 
 	// Pass /debug/ to the default ServeMux, all the default debug
-	// handlers are installed there.
-	mux.Handle(
-		"/debug/",
-		handlers.GZIPHandler(http.DefaultServeMux, nil))
+	// handlers are installed there. Add a debug handler for the
+	// LoadBalancer data. Gzip the responses.
+	debugMux := http.NewServeMux()
+	debugMux.Handle("/debug/lbv2", h.lb)
+	debugMux.Handle("/", http.DefaultServeMux)
+	mux.Handle("/debug/", handlers.GZIPHandler(debugMux, nil))
 
 	// Optionally enable a reverse proxy to the local Icecast for
 	// the direct stream URLs (below IcecastMountPrefix).
diff --git a/fe/http_debug.go b/fe/http_debug.go
index 4861be2a0edb9b82de5609dcf8d7ab347ea7843b..cb656ef3287643c2b7eaecaaa9719a2e3269213d 100644
--- a/fe/http_debug.go
+++ b/fe/http_debug.go
@@ -2,10 +2,10 @@ package fe
 
 import (
 	"fmt"
+	"html/template"
 	"net/http"
 	"sort"
 	"sync"
-	"text/template"
 	"time"
 )
 
diff --git a/fe/http_test.go b/fe/http_test.go
index 531e5919a11ae41ff87320a343fe16dc32f36ab0..2b849fc6a7dae2dd0fc4f4df0c78396712352d62 100644
--- a/fe/http_test.go
+++ b/fe/http_test.go
@@ -103,6 +103,16 @@ func TestHttpRedirector_Static(t *testing.T) {
 	}
 }
 
+func TestHttpRedirector_LBDebugPage(t *testing.T) {
+	_, srv := createTestHttpServer(t)
+	defer srv.Close()
+
+	data := doHttpRequest(t, "GET", srv.URL+"/debug/lbv2", 200)
+	if !strings.Contains(data, "node1") {
+		t.Errorf("Bad response:\n%s", data)
+	}
+}
+
 type httpTestContext struct {
 	srv             *httptest.Server
 	targetSrv       *httptest.Server
diff --git a/fe/lbv2/debug.go b/fe/lbv2/debug.go
new file mode 100644
index 0000000000000000000000000000000000000000..6bf69cdd2b9da7686b1e0612f914938cec600e4a
--- /dev/null
+++ b/fe/lbv2/debug.go
@@ -0,0 +1,80 @@
+package lbv2
+
+import (
+	"fmt"
+	"html/template"
+	"net/http"
+)
+
+const debugText = `<html>
+    <body>
+    <title>Load Balancer</title>
+
+    <h3>Query costs</h3>
+    <table>
+      <tr><th>Node</th><th>Requests</th><th>Utilization/Cost</th></tr>
+      {{$dimensions := .Dimensions}}
+      {{range .Nodes}}
+      <tr>
+        <td>{{.Name}}</td>
+        <td>{{.Requests}}</td>
+        {{range $d := $dimensions}}
+          {{$data := index .Data $d}}
+          <td>
+          {{$data.PredictedUtilization}}/{{$data.ReportedUtilization}}/{{$data.Cost}}
+          </td>
+        {{end}}
+      </tr>
+      {{end}}
+    </table>
+    </body>
+    </html>`
+
+var debugTmpl = template.Must(template.New("lbv2 debug").Parse(debugText))
+
+type nodeDebugData struct {
+	Name     string
+	Requests int
+	Data     map[int]costAndUtil
+}
+
+type costAndUtil struct {
+	ReportedUtilization  float64
+	PredictedUtilization float64
+	Cost                 float64
+}
+
+func (l *LoadBalancer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	// Build a view of the cost/utilization data.
+	l.lock.Lock()
+	var nodes []nodeDebugData
+	for _, n := range l.nodes {
+		ndata := nodeDebugData{Name: n.Name(), Data: make(map[int]costAndUtil)}
+		for dim, pred := range l.predictors {
+			util := n.Utilization(dim)
+			ndata.Requests = util.Requests
+			ndata.Data[dim] = costAndUtil{
+				ReportedUtilization:  util.Utilization,
+				PredictedUtilization: pred.Utilization(n),
+				Cost:                 float64(pred.cost[n.Name()]),
+			}
+		}
+		nodes = append(nodes, ndata)
+	}
+	var dimensions []int
+	for dim := range l.predictors {
+		dimensions = append(dimensions, dim)
+	}
+	l.lock.Unlock()
+
+	ctx := struct {
+		Nodes         []nodeDebugData
+		Dimensions    []int
+		NumDimensions int
+	}{nodes, dimensions, len(dimensions)}
+
+	err := debugTmpl.Execute(w, ctx)
+	if err != nil {
+		fmt.Fprintln(w, "debug: error executing template: ", err.Error())
+	}
+}