diff --git a/README.md b/README.md
index 2bd10e1f2ff245c58db47b1333305426641e260b..7b657b174315450422a55f7daa97a21a39bc9773 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,6 @@ i'll lyk when its done
 | Load balancing of read queries | :white_check_mark:          | :white_check_mark: | Using random between replicas. Primary is included when `primary_reads_enabled` is enabled (default).                                            |
 | Sharding                       | :white_check_mark:          | :white_check_mark: | Transactions are sharded using `SET SHARD TO` and `SET SHARDING KEY TO` syntax extensions; see examples below.                                        |
 | Failover                       | :white_check_mark:          | :white_check_mark: | Replicas are tested with a health check. If a health check fails, remaining replicas are attempted; see below for algorithm description and examples. |
-| Statistics                     | :white_check_mark:          | :white_check_mark: | Statistics available in the admin database (`pgcat` and `pgbouncer`) with `SHOW STATS`, `SHOW POOLS` and others.                                      |
 | Live configuration reloading   | :white_check_mark:          | kind of            | Reload supported settings with a `SIGHUP` to the process, e.g. `kill -s SIGHUP $(pgrep pgcat)` or `RELOAD` query issued to the admin database.        |
 | Client authentication          | :white_check_mark: :wrench: | same as them       | MD5 password authentication is supported, SCRAM is on the roadmap; one user is used to connect to Postgres with both SCRAM and MD5 supported.         |
 | Admin database                 | :white_check_mark:          | :white_check_mark: | The admin database, similar to PgBouncer's, allows to query for statistics and reload the configuration.                                              |
@@ -123,7 +122,6 @@ docker compose up --exit-code-from main # This will also produce coverage report
 | Load balancing        | :white_check_mark: | :white_check_mark:  | We could test this by emitting statistics for each replica and compare them.                                             |
 | Failover              | :white_check_mark: | :white_check_mark:  | Misconfigure a replica in `pgcat.toml` and watch it forward queries to spares. CI testing is using Toxiproxy.            |
 | Sharding              | :white_check_mark: | :white_check_mark:  | See `tests/sharding` and `tests/ruby` for an Rails/ActiveRecord example.                                                 |
-| Statistics            | :white_check_mark: | :white_check_mark:  | Query the admin database with `psql -h 127.0.0.1 -p 6432 -d pgbouncer -c 'SHOW STATS'`.                                  |
 | Live config reloading | :white_check_mark: | :white_check_mark:  | Run `kill -s SIGHUP $(pgrep pgcat)` and watch the config reload.                                                         |
 
 ## Usage
@@ -264,14 +262,6 @@ SET SERVER ROLE TO 'auto'; -- let the query router figure out where the query sh
 SELECT * FROM users WHERE email = 'test@example.com'; -- shard setting lasts until set again; we are reading from the primary
 ```
 
-### Statistics reporting
-
-The stats are very similar to what Pgbouncer reports and the names are kept to be comparable. They are accessible by querying the admin database `pgcat`, and `pgbouncer` for compatibility.
-
-```
-psql -h 127.0.0.1 -p 6432 -d pgbouncer -c 'SHOW DATABASES'
-```
-
 ### Live configuration reloading
 
 The config can be reloaded by sending a `kill -s SIGHUP` to the process or by querying `RELOAD` to the admin database. Not all settings are currently supported by live reload:
diff --git a/lib/gat/admin/admin.go b/lib/gat/admin/admin.go
index 8780ac73eb4304589d9799b00afcfc3905b90a8c..79c34b57f22e9a8441a26c1f6cb5aa3a9f710741 100644
--- a/lib/gat/admin/admin.go
+++ b/lib/gat/admin/admin.go
@@ -3,8 +3,6 @@ package admin
 import (
 	"context"
 	"errors"
-	"fmt"
-	"time"
 
 	"gfx.cafe/gfx/pggat/lib/config"
 	"gfx.cafe/gfx/pggat/lib/gat"
@@ -87,18 +85,7 @@ func New(g gat.Gat) *Database {
 		database: out,
 	}
 	out.r = cmux.NewMapMux[gat.Client, error]()
-	out.r.Register([]string{"show", "stats_totals"}, func(client gat.Client, _ []string) error {
-		return out.showStats(client, true, false)
-	})
-	out.r.Register([]string{"show", "stats_averages"}, func(client gat.Client, _ []string) error {
-		return out.showStats(client, false, true)
-	})
-	out.r.Register([]string{"show", "stats"}, func(client gat.Client, _ []string) error {
-		return out.showStats(client, true, true)
-	})
-	out.r.Register([]string{"show", "totals"}, func(client gat.Client, _ []string) error {
-		return out.showTotals(client)
-	})
+
 	out.r.Register([]string{"show", "servers"}, func(_ gat.Client, _ []string) error {
 		return nil
 	})
@@ -177,350 +164,6 @@ func New(g gat.Gat) *Database {
 	return out
 }
 
-func (p *Database) showStats(client gat.Client, totals, averages bool) error {
-	rowDesc := new(protocol.RowDescription)
-	rowDesc.Fields.Fields = []protocol.FieldsRowDescriptionFields{
-		{
-			Name:         "database",
-			DataType:     DataType_String,
-			DataTypeSize: -1,
-			TypeModifier: -1,
-		},
-	}
-	if totals {
-		rowDesc.Fields.Fields = append(rowDesc.Fields.Fields,
-			protocol.FieldsRowDescriptionFields{
-				Name:         "total_xact_count",
-				DataType:     DataType_Int64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "total_query_count",
-				DataType:     DataType_Int64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "total_received",
-				DataType:     DataType_Int64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "total_sent",
-				DataType:     DataType_Int64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "total_xact_time",
-				DataType:     DataType_Int64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "total_query_time",
-				DataType:     DataType_Int64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "total_wait_time",
-				DataType:     DataType_Int64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			})
-	}
-	if averages {
-		rowDesc.Fields.Fields = append(rowDesc.Fields.Fields,
-			protocol.FieldsRowDescriptionFields{
-				Name:         "avg_xact_count",
-				DataType:     DataType_Float64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "avg_query_count",
-				DataType:     DataType_Float64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "avg_recv",
-				DataType:     DataType_Float64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "avg_sent",
-				DataType:     DataType_Float64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "avg_xact_time",
-				DataType:     DataType_Float64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "avg_query_time",
-				DataType:     DataType_Float64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			},
-			protocol.FieldsRowDescriptionFields{
-				Name:         "avg_wait_time",
-				DataType:     DataType_Float64,
-				DataTypeSize: 8,
-				TypeModifier: -1,
-			})
-	}
-	err := client.Send(rowDesc)
-	if err != nil {
-		return err
-	}
-	for name, pl := range p.gat.GetDatabases() {
-		stats := pl.GetStats()
-		if stats == nil {
-			continue
-		}
-		row := new(protocol.DataRow)
-		row.Fields.Columns = []protocol.FieldsDataRowColumns{
-			{
-				[]byte(name),
-			},
-		}
-		if totals {
-			row.Fields.Columns = append(row.Fields.Columns,
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%d", stats.TotalXactCount())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%d", stats.TotalQueryCount())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%d", stats.TotalReceived())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%d", stats.TotalSent())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%d", stats.TotalXactTime())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%d", stats.TotalQueryTime())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%d", stats.TotalWaitTime())),
-				})
-		}
-		if averages {
-			row.Fields.Columns = append(row.Fields.Columns,
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%f", stats.AvgXactCount())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%f", stats.AvgQueryCount())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%f", stats.AvgRecv())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%f", stats.AvgSent())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%f", stats.AvgXactTime())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%f", stats.AvgQueryTime())),
-				},
-				protocol.FieldsDataRowColumns{
-					[]byte(fmt.Sprintf("%f", stats.AvgWaitTime())),
-				})
-		}
-		err = client.Send(row)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (p *Database) showTotals(client gat.Client) error {
-	rowDesc := new(protocol.RowDescription)
-	rowDesc.Fields.Fields = []protocol.FieldsRowDescriptionFields{
-		{
-			Name:         "total_xact_count",
-			DataType:     DataType_Int64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "total_query_count",
-			DataType:     DataType_Int64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "total_received",
-			DataType:     DataType_Int64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "total_sent",
-			DataType:     DataType_Int64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "total_xact_time",
-			DataType:     DataType_Int64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "total_query_time",
-			DataType:     DataType_Int64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "total_wait_time",
-			DataType:     DataType_Int64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "avg_xact_count",
-			DataType:     DataType_Float64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "avg_query_count",
-			DataType:     DataType_Float64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "avg_recv",
-			DataType:     DataType_Float64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "avg_sent",
-			DataType:     DataType_Float64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "avg_xact_time",
-			DataType:     DataType_Float64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "avg_query_time",
-			DataType:     DataType_Float64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-		{
-			Name:         "avg_wait_time",
-			DataType:     DataType_Float64,
-			DataTypeSize: 8,
-			TypeModifier: -1,
-		},
-	}
-	err := client.Send(rowDesc)
-	if err != nil {
-		return err
-	}
-
-	var totalXactCount, totalQueryCount, totalWaitCount, totalReceived, totalSent, totalXactTime, totalQueryTime, totalWaitTime int64
-	var alive time.Duration
-
-	for _, pl := range p.gat.GetDatabases() {
-		stats := pl.GetStats()
-		if stats == nil {
-			continue
-		}
-		totalXactCount += stats.TotalXactCount()
-		totalQueryCount += stats.TotalQueryCount()
-		totalWaitCount += stats.TotalWaitCount()
-		totalReceived += stats.TotalReceived()
-		totalSent += stats.TotalSent()
-		totalXactTime += stats.TotalXactTime()
-		totalQueryTime += stats.TotalQueryTime()
-		totalWaitTime += stats.TotalWaitTime()
-
-		active := stats.TimeActive()
-		if active > alive {
-			alive = active
-		}
-	}
-
-	avgXactCount := float64(totalXactCount) / alive.Seconds()
-	avgQueryCount := float64(totalQueryCount) / alive.Seconds()
-	avgReceive := float64(totalReceived) / alive.Seconds()
-	avgSent := float64(totalSent) / alive.Seconds()
-	avgXactTime := float64(totalXactTime) / float64(totalXactCount)
-	avgQueryTime := float64(totalQueryTime) / float64(totalQueryCount)
-	avgWaitTime := float64(totalWaitTime) / float64(totalWaitCount)
-
-	row := new(protocol.DataRow)
-	row.Fields.Columns = []protocol.FieldsDataRowColumns{
-		{
-			[]byte(fmt.Sprintf("%d", totalXactCount)),
-		},
-		{
-			[]byte(fmt.Sprintf("%d", totalQueryCount)),
-		},
-		{
-			[]byte(fmt.Sprintf("%d", totalReceived)),
-		},
-		{
-			[]byte(fmt.Sprintf("%d", totalSent)),
-		},
-		{
-			[]byte(fmt.Sprintf("%d", totalXactTime)),
-		},
-		{
-			[]byte(fmt.Sprintf("%d", totalQueryTime)),
-		},
-		{
-			[]byte(fmt.Sprintf("%d", totalWaitTime)),
-		},
-		{
-			[]byte(fmt.Sprintf("%f", avgXactCount)),
-		},
-		{
-			[]byte(fmt.Sprintf("%f", avgQueryCount)),
-		},
-		{
-			[]byte(fmt.Sprintf("%f", avgReceive)),
-		},
-		{
-			[]byte(fmt.Sprintf("%f", avgSent)),
-		},
-		{
-			[]byte(fmt.Sprintf("%f", avgXactTime)),
-		},
-		{
-			[]byte(fmt.Sprintf("%f", avgQueryTime)),
-		},
-		{
-			[]byte(fmt.Sprintf("%f", avgWaitTime)),
-		},
-	}
-
-	return client.Send(row)
-}
-
 func (p *Database) GetUser(name string) *config.User {
 	u := getAdminUser(p.gat)
 	if name != u.Name {
@@ -551,10 +194,6 @@ func (p *Database) GetPools() []gat.Pool {
 	}
 }
 
-func (p *Database) GetStats() *gat.PoolStats {
-	return nil
-}
-
 func (p *Database) EnsureConfig(c *config.Pool) {
 	// TODO
 }
diff --git a/lib/gat/database/database.go b/lib/gat/database/database.go
index a54060b6a885b77f1736a728787e6a30d3bf016a..51ecefeedc5c6a2dcf4ceae007b5c8f042cceb75 100644
--- a/lib/gat/database/database.go
+++ b/lib/gat/database/database.go
@@ -1,10 +1,11 @@
 package database
 
 import (
+	"sync"
+
 	"gfx.cafe/gfx/pggat/lib/gat/database/query_router"
 	"gfx.cafe/gfx/pggat/lib/gat/pool/session"
 	"gfx.cafe/gfx/pggat/lib/gat/pool/transaction"
-	"sync"
 
 	"gfx.cafe/gfx/pggat/lib/config"
 	"gfx.cafe/gfx/pggat/lib/gat"
@@ -16,8 +17,6 @@ type Database struct {
 	connPools map[string]gat.Pool
 	name      string
 
-	stats *gat.PoolStats
-
 	router *query_router.QueryRouter
 
 	dialer gat.Dialer
@@ -28,7 +27,6 @@ type Database struct {
 func New(dialer gat.Dialer, name string, conf *config.Pool) *Database {
 	pool := &Database{
 		connPools: make(map[string]gat.Pool),
-		stats:     gat.NewPoolStats(),
 		router:    query_router.DefaultRouter(conf),
 		name:      name,
 
@@ -102,8 +100,4 @@ func (p *Database) GetPools() []gat.Pool {
 	return out
 }
 
-func (p *Database) GetStats() *gat.PoolStats {
-	return p.stats
-}
-
 var _ gat.Database = (*Database)(nil)
diff --git a/lib/gat/interfaces.go b/lib/gat/interfaces.go
index 6c13c30c8da7a543b6f2c1432cf925232d8981cb..0a02ebed5b95a2d634bd428a6eb9f352ef181e94 100644
--- a/lib/gat/interfaces.go
+++ b/lib/gat/interfaces.go
@@ -2,10 +2,11 @@ package gat
 
 import (
 	"context"
-	"gfx.cafe/gfx/pggat/lib/config"
-	"gfx.cafe/gfx/pggat/lib/gat/protocol"
 	"net"
 	"time"
+
+	"gfx.cafe/gfx/pggat/lib/config"
+	"gfx.cafe/gfx/pggat/lib/gat/protocol"
 )
 
 type ClientID struct {
@@ -68,8 +69,6 @@ type Database interface {
 	WithUser(name string) Pool
 	GetPools() []Pool
 
-	GetStats() *PoolStats
-
 	EnsureConfig(c *config.Pool)
 }
 
diff --git a/lib/gat/stats.go b/lib/gat/stats.go
deleted file mode 100644
index ec56eb64c89117363a7e71c3df376e5e3105ac56..0000000000000000000000000000000000000000
--- a/lib/gat/stats.go
+++ /dev/null
@@ -1,128 +0,0 @@
-package gat
-
-import (
-	"sync/atomic"
-	"time"
-)
-
-type PoolStats struct {
-	start time.Time
-
-	xactCount  atomic.Int64
-	queryCount atomic.Int64
-	waitCount  atomic.Int64
-	received   atomic.Int64
-	sent       atomic.Int64
-	xactTime   atomic.Int64
-	queryTime  atomic.Int64
-	waitTime   atomic.Int64
-}
-
-func NewPoolStats() *PoolStats {
-	return &PoolStats{
-		start: time.Now(),
-	}
-}
-
-func (s *PoolStats) TimeActive() time.Duration {
-	return time.Now().Sub(s.start)
-}
-
-func (s *PoolStats) TotalXactCount() int64 {
-	return s.xactCount.Load()
-}
-
-func (s *PoolStats) TotalQueryCount() int64 {
-	return s.queryCount.Load()
-}
-
-func (s *PoolStats) TotalWaitCount() int64 {
-	return s.waitCount.Load()
-}
-
-func (s *PoolStats) TotalReceived() int64 {
-	return s.received.Load()
-}
-
-func (s *PoolStats) AddTotalReceived(amount int64) {
-	s.received.Add(amount)
-}
-
-func (s *PoolStats) TotalSent() int64 {
-	return s.sent.Load()
-}
-
-func (s *PoolStats) AddTotalSent(amount int64) {
-	s.sent.Add(amount)
-}
-
-func (s *PoolStats) TotalXactTime() int64 {
-	return s.xactTime.Load()
-}
-
-func (s *PoolStats) AddXactTime(time int64) {
-	s.xactCount.Add(1)
-	s.xactTime.Add(time)
-}
-
-func (s *PoolStats) TotalQueryTime() int64 {
-	return s.queryTime.Load()
-}
-
-func (s *PoolStats) AddQueryTime(time int64) {
-	s.queryCount.Add(1)
-	s.queryTime.Add(time)
-}
-
-func (s *PoolStats) TotalWaitTime() int64 {
-	return s.waitTime.Load()
-}
-
-func (s *PoolStats) AddWaitTime(time int64) {
-	s.waitCount.Add(1)
-	s.waitTime.Add(time)
-}
-
-func (s *PoolStats) AvgXactCount() float64 {
-	seconds := s.TimeActive().Seconds()
-	return float64(s.xactCount.Load()) / seconds
-}
-
-func (s *PoolStats) AvgQueryCount() float64 {
-	seconds := s.TimeActive().Seconds()
-	return float64(s.queryCount.Load()) / seconds
-}
-
-func (s *PoolStats) AvgRecv() float64 {
-	seconds := s.TimeActive().Seconds()
-	return float64(s.received.Load()) / seconds
-}
-
-func (s *PoolStats) AvgSent() float64 {
-	seconds := s.TimeActive().Seconds()
-	return float64(s.sent.Load()) / seconds
-}
-
-func (s *PoolStats) AvgXactTime() float64 {
-	xactCount := s.xactCount.Load()
-	if xactCount == 0 {
-		return 0
-	}
-	return float64(s.xactTime.Load()) / float64(xactCount)
-}
-
-func (s *PoolStats) AvgQueryTime() float64 {
-	queryCount := s.queryCount.Load()
-	if queryCount == 0 {
-		return 0
-	}
-	return float64(s.queryTime.Load()) / float64(queryCount)
-}
-
-func (s *PoolStats) AvgWaitTime() float64 {
-	waitCount := s.waitCount.Load()
-	if waitCount == 0 {
-		return 0
-	}
-	return float64(s.waitTime.Load()) / float64(waitCount)
-}