diff --git a/lib/fed/packets/v3.0/commandcomplete.go b/lib/fed/packets/v3.0/commandcomplete.go
new file mode 100644
index 0000000000000000000000000000000000000000..d2f2cb863759ff8c0aa4d2755ca61b60d62578b9
--- /dev/null
+++ b/lib/fed/packets/v3.0/commandcomplete.go
@@ -0,0 +1,19 @@
+package packets
+
+import "pggat/lib/fed"
+
+type CommandComplete string
+
+func (T *CommandComplete) ReadFromPacket(packet fed.Packet) bool {
+	if packet.Type() != TypeCommandComplete {
+		return false
+	}
+	packet.ReadString((*string)(T))
+	return true
+}
+
+func (T *CommandComplete) IntoPacket() fed.Packet {
+	packet := fed.NewPacket(TypeCommandComplete, len(*T)+1)
+	packet = packet.AppendString(string(*T))
+	return packet
+}
diff --git a/lib/middleware/middlewares/eqp/state.go b/lib/middleware/middlewares/eqp/state.go
index ea122f63b5c98817062d8191877b7b12ad6518e9..7079c6b122126dc285384921071033c1dfc98a48 100644
--- a/lib/middleware/middlewares/eqp/state.go
+++ b/lib/middleware/middlewares/eqp/state.go
@@ -5,6 +5,7 @@ import (
 
 	"pggat/lib/fed"
 	packets "pggat/lib/fed/packets/v3.0"
+	"pggat/lib/util/maps"
 	"pggat/lib/util/ring"
 )
 
@@ -90,6 +91,8 @@ func (T *State) S2C(packet fed.Packet) {
 		T.ParseComplete()
 	case packets.TypeBindComplete:
 		T.BindComplete()
+	case packets.TypeCommandComplete:
+		T.CommandComplete(packet)
 	case packets.TypeReadyForQuery:
 		T.ReadyForQuery(packet)
 	}
@@ -179,6 +182,22 @@ func (T *State) Query() {
 	delete(T.preparedStatements, "")
 }
 
+// CommandComplete clobbers everything if DISCARD ALL | DEALLOCATE | CLOSE
+func (T *State) CommandComplete(packet fed.Packet) {
+	var commandComplete packets.CommandComplete
+	if !commandComplete.ReadFromPacket(packet) {
+		return
+	}
+
+	if commandComplete == "DISCARD ALL" {
+		maps.Clear(T.preparedStatements)
+		maps.Clear(T.portals)
+		T.pendingPreparedStatements.Clear()
+		T.pendingPortals.Clear()
+		T.pendingCloses.Clear()
+	}
+}
+
 // ReadyForQuery clobbers portals if state == 'I' and pending. Execute on ReadyForQuery S->C
 func (T *State) ReadyForQuery(packet fed.Packet) {
 	var state byte
diff --git a/test/tester_test.go b/test/tester_test.go
index 6d7468aa0f24a6b9291cf6bbd88ff8bd8a7871bd..cfdb1b47f56aa27eecc4db0da2d19a96baa035fd 100644
--- a/test/tester_test.go
+++ b/test/tester_test.go
@@ -47,7 +47,7 @@ func TestTester(t *testing.T) {
 		Password: password,
 	}
 
-	for i := 0; i < 1; i++ {
+	for i := 0; i < 10; i++ {
 		var g gat.PoolsMap
 		p := pool.NewPool(transaction.Apply(pool.Options{
 			Credentials: creds,
@@ -153,6 +153,7 @@ func TestTester(t *testing.T) {
 		tests.EQP8,
 		tests.CopyOut0,
 		tests.CopyOut1,
+		tests.DiscardAll,
 	); err != nil {
 		fmt.Print(err.Error())
 		t.Fail()
diff --git a/test/tests/discard_all.go b/test/tests/discard_all.go
new file mode 100644
index 0000000000000000000000000000000000000000..4bd056514ddad958ffa693c9331decf1beda96b2
--- /dev/null
+++ b/test/tests/discard_all.go
@@ -0,0 +1,30 @@
+package tests
+
+import (
+	"pggat/test"
+	"pggat/test/inst"
+)
+
+var DiscardAll = test.Test{
+	Name: "Discard All",
+	Instructions: []inst.Instruction{
+		inst.Parse{
+			Destination: "a",
+			Query:       "select 0",
+		},
+		inst.Bind{
+			Destination: "a",
+			Source:      "a",
+		},
+		inst.Sync{},
+		inst.SimpleQuery("discard all"),
+		inst.DescribePreparedStatement("a"),
+		inst.Sync{},
+		inst.Parse{
+			Destination: "a",
+			Query:       "select 0",
+		},
+		inst.DescribePreparedStatement("a"),
+		inst.Sync{},
+	},
+}