diff --git a/lib/gat/modes/zalando_operator_discovery/server.go b/lib/gat/modes/zalando_operator_discovery/server.go
index 8b15f60ad635fdda5ee9058541757459ca5f2add..d3e45940d9d603f01533b1029f3e204f027ec5c8 100644
--- a/lib/gat/modes/zalando_operator_discovery/server.go
+++ b/lib/gat/modes/zalando_operator_discovery/server.go
@@ -2,6 +2,7 @@ package zalando_operator_discovery
 
 import (
 	"context"
+	"crypto/tls"
 
 	acidzalando "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do"
 	v1acid "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1"
@@ -12,15 +13,32 @@ import (
 	"k8s.io/client-go/tools/cache"
 	"tuxpa.in/a/zlog/log"
 
+	"pggat/lib/auth/credentials"
+	"pggat/lib/bouncer"
+	"pggat/lib/bouncer/backends/v0"
+	"pggat/lib/bouncer/frontends/v0"
+	"pggat/lib/gat"
+	"pggat/lib/gat/pool"
+	"pggat/lib/gat/pool/dialer"
+	"pggat/lib/gat/pool/pools/transaction"
+	"pggat/lib/gat/pool/recipe"
 	"pggat/lib/util/flip"
+	"pggat/lib/util/strutil"
 )
 
+type mapKey struct {
+	User     string
+	Database string
+}
+
 type Server struct {
 	config *Config
 
 	k8s k8sutil.KubernetesClient
 
 	postgresqlInformer cache.SharedIndexInformer
+
+	pools gat.PoolsMap
 }
 
 func NewServer(config *Config) (*Server, error) {
@@ -96,7 +114,51 @@ func (T *Server) updatePostgresql(oldPsql *v1acid.Postgresql, newPsql *v1acid.Po
 			// TODO(garet) lookup config map to get this format (what a pain)
 			secretName := user + "." + newPsql.Name + ".credentials." + v1acid.PostgresCRDResourceKind + "." + acidzalando.GroupName
 
-			T.k8s.Secrets(T.config.Namespace).Get(context.Background(), secretName, v1.GetOptions{})
+			secret, err := T.k8s.Secrets(T.config.Namespace).Get(context.Background(), secretName, v1.GetOptions{})
+			if err != nil {
+				log.Printf("error getting secret: %v", err)
+				return
+			}
+
+			password, ok := secret.Data["password"]
+			if !ok {
+				log.Println("failed to get password in secret :(")
+				return
+			}
+
+			creds := credentials.Cleartext{
+				Username: user,
+				Password: string(password),
+			}
+
+			for database := range newPsql.Spec.Databases {
+				d := dialer.Net{
+					Network: "tcp",
+					Address: newPsql.Name + "." + T.config.Namespace + ".svc.cluster.local:5432", // TODO(garet) lookup port from config map
+					AcceptOptions: backends.AcceptOptions{
+						SSLMode: bouncer.SSLModePrefer,
+						SSLConfig: &tls.Config{
+							InsecureSkipVerify: true,
+						},
+						Credentials: creds,
+						Database:    database,
+					},
+				}
+
+				poolOptions := pool.Options{
+					Credentials: creds,
+				}
+				p := transaction.NewPool(poolOptions)
+
+				recipeOptions := recipe.Options{
+					Dialer: d,
+				}
+				r := recipe.NewRecipe(recipeOptions)
+
+				p.AddRecipe("service", r)
+
+				T.pools.Add(user, database, p)
+			}
 		}
 	}
 }
@@ -113,5 +175,22 @@ func (T *Server) ListenAndServe() error {
 		return nil
 	})
 
+	bank.Queue(func() error {
+		listen := ":5432" // TODO(garet) use port
+
+		log.Printf("listening on %s", listen)
+
+		return gat.ListenAndServe("tcp", listen, frontends.AcceptOptions{
+			AllowedStartupOptions: []strutil.CIString{
+				strutil.MakeCIString("client_encoding"),
+				strutil.MakeCIString("datestyle"),
+				strutil.MakeCIString("timezone"),
+				strutil.MakeCIString("standard_conforming_strings"),
+				strutil.MakeCIString("application_name"),
+			},
+			// TODO(garet)
+		}, &T.pools)
+	})
+
 	return bank.Wait()
 }