diff --git a/codegen/protocol/packets.tmpl b/codegen/protocol/packets.tmpl
index 99f1799aa0b33ed2dd9df2f654cb713ae86df87e..9a27869763e7979f29bb5bd4d409c58e113b89c5 100644
--- a/codegen/protocol/packets.tmpl
+++ b/codegen/protocol/packets.tmpl
@@ -75,6 +75,55 @@ import "io"
     {{end -}}
 {{end -}}
 
+{{define "writeFieldL1" -}}
+    {{$parent := (index . 0) -}}
+    {{$field := (index . 1) -}}
+    {{$location := (index . 2) -}}
+
+    {{if $field.Struct -}}
+        temp, err = {{$location}}.Write(writer)
+        if err != nil {
+            return
+        }
+        length += temp
+    {{- else if $field.Type -}}
+        temp, err = Write{{camelCase $field.Type}}(writer, {{$location}})
+        if err != nil {
+            return
+        }
+        length += temp
+    {{- end -}}
+{{end -}}
+
+{{define "writeField" -}}
+    {{$parent := (index . 0) -}}
+    {{$field := (index . 1) -}}
+
+    {{if $field.If -}}
+        if {{$field.If}} {
+    {{end -}}
+
+    {{if $field.LengthPrefixed -}}
+        temp, err = Write{{camelCase $field.LengthPrefixed}}(writer, {{$field.LengthPrefixed}}(len(T.{{$field.Name}})))
+        if err != nil {
+            return
+        }
+        length += temp
+    {{end -}}
+
+    {{if or $field.LengthPrefixed $field.ArrayLength -}}
+        for _, v := range T.{{$field.Name}} {
+            {{template "writeFieldL1" (list $parent $field "v")}}
+        }
+    {{else -}}
+        {{template "writeFieldL1" (list $parent $field (printf "T.%s" $field.Name))}}
+    {{end -}}
+
+    {{if $field.If -}}
+        }
+    {{end -}}
+{{end -}}
+
 {{define "declareFields" -}}
     {{$parent := (index . 0) -}}
     {{$struct := (index . 1) -}}
@@ -97,6 +146,15 @@ import "io"
         {{end -}}
         return
     }
+
+    func (T *Fields{{$parent}}) Write(writer io.Writer) (length int, err error) {
+        var temp int
+        {{range $idx, $field := $struct.Fields -}}
+            {{template "writeField" (list $parent $field) -}}
+        {{end -}}
+        _ = temp
+        return
+    }
 {{end -}}
 
 {{range $name, $packet := . -}}
diff --git a/lib/gat/protocol/backend.go b/lib/gat/protocol/backend.go
index eac41fa49d5a94052f6f0e984e57673cf79a3083..8e193dec60c6808a6623c8a2179d77bb1e36f7fc 100644
--- a/lib/gat/protocol/backend.go
+++ b/lib/gat/protocol/backend.go
@@ -20,6 +20,19 @@ func (T *FieldsAuthentication) Read(payloadLength int, reader io.Reader) (err er
 	return
 }
 
+func (T *FieldsAuthentication) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	for _, v := range T.Data {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type Authentication struct {
 	fields FieldsAuthentication
 }
@@ -41,6 +54,22 @@ func (T *FieldsBackendKeyData) Read(payloadLength int, reader io.Reader) (err er
 	return
 }
 
+func (T *FieldsBackendKeyData) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.ProcessID)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, T.SecretKey)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type BackendKeyData struct {
 	fields FieldsBackendKeyData
 }
@@ -52,6 +81,12 @@ func (T *FieldsBindComplete) Read(payloadLength int, reader io.Reader) (err erro
 	return
 }
 
+func (T *FieldsBindComplete) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type BindComplete struct {
 	fields FieldsBindComplete
 }
@@ -63,6 +98,12 @@ func (T *FieldsCloseComplete) Read(payloadLength int, reader io.Reader) (err err
 	return
 }
 
+func (T *FieldsCloseComplete) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type CloseComplete struct {
 	fields FieldsCloseComplete
 }
@@ -79,6 +120,17 @@ func (T *FieldsCommandComplete) Read(payloadLength int, reader io.Reader) (err e
 	return
 }
 
+func (T *FieldsCommandComplete) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Data)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type CommandComplete struct {
 	fields FieldsCommandComplete
 }
@@ -108,6 +160,29 @@ func (T *FieldsCopyBothResponse) Read(payloadLength int, reader io.Reader) (err
 	return
 }
 
+func (T *FieldsCopyBothResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt8(writer, T.Format)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, int16(len(T.ColumnFormats)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.ColumnFormats {
+		temp, err = WriteInt16(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type CopyBothResponse struct {
 	fields FieldsCopyBothResponse
 }
@@ -137,6 +212,29 @@ func (T *FieldsCopyInResponse) Read(payloadLength int, reader io.Reader) (err er
 	return
 }
 
+func (T *FieldsCopyInResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt8(writer, T.Format)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, int16(len(T.ColumnFormats)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.ColumnFormats {
+		temp, err = WriteInt16(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type CopyInResponse struct {
 	fields FieldsCopyInResponse
 }
@@ -166,6 +264,29 @@ func (T *FieldsCopyOutResponse) Read(payloadLength int, reader io.Reader) (err e
 	return
 }
 
+func (T *FieldsCopyOutResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt8(writer, T.Format)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, int16(len(T.ColumnFormats)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.ColumnFormats {
+		temp, err = WriteInt16(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type CopyOutResponse struct {
 	fields FieldsCopyOutResponse
 }
@@ -190,6 +311,24 @@ func (T *FieldsDataRowColumns) Read(payloadLength int, reader io.Reader) (err er
 	return
 }
 
+func (T *FieldsDataRowColumns) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, int32(len(T.Bytes)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Bytes {
+		temp, err = WriteInt8(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type FieldsDataRow struct {
 	Columns []FieldsDataRowColumns
 }
@@ -210,6 +349,24 @@ func (T *FieldsDataRow) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsDataRow) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt16(writer, int16(len(T.Columns)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Columns {
+		temp, err = v.Write(writer)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type DataRow struct {
 	fields FieldsDataRow
 }
@@ -221,6 +378,12 @@ func (T *FieldsEmptyQueryResponse) Read(payloadLength int, reader io.Reader) (er
 	return
 }
 
+func (T *FieldsEmptyQueryResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type EmptyQueryResponse struct {
 	fields FieldsEmptyQueryResponse
 }
@@ -242,6 +405,22 @@ func (T *FieldsErrorResponse) Read(payloadLength int, reader io.Reader) (err err
 	return
 }
 
+func (T *FieldsErrorResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteByte(writer, T.Code)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.Value)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type ErrorResponse struct {
 	fields FieldsErrorResponse
 }
@@ -266,6 +445,24 @@ func (T *FieldsFunctionCallResponse) Read(payloadLength int, reader io.Reader) (
 	return
 }
 
+func (T *FieldsFunctionCallResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, int32(len(T.Result)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Result {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type FunctionCallResponse struct {
 	fields FieldsFunctionCallResponse
 }
@@ -295,6 +492,29 @@ func (T *FieldsNegotiateProtocolVersion) Read(payloadLength int, reader io.Reade
 	return
 }
 
+func (T *FieldsNegotiateProtocolVersion) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.MinorVersion)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, int32(len(T.NotRecognized)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.NotRecognized {
+		temp, err = WriteString(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type NegotiateProtocolVersion struct {
 	fields FieldsNegotiateProtocolVersion
 }
@@ -306,6 +526,12 @@ func (T *FieldsNoData) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsNoData) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type NoData struct {
 	fields FieldsNoData
 }
@@ -329,6 +555,24 @@ func (T *FieldsNoticeResponse) Read(payloadLength int, reader io.Reader) (err er
 	return
 }
 
+func (T *FieldsNoticeResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteByte(writer, T.Type)
+	if err != nil {
+		return
+	}
+	length += temp
+	if T.Type != 0 {
+		temp, err = WriteString(writer, T.Value)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type NoticeResponse struct {
 	fields FieldsNoticeResponse
 }
@@ -355,6 +599,27 @@ func (T *FieldsNotificationResponse) Read(payloadLength int, reader io.Reader) (
 	return
 }
 
+func (T *FieldsNotificationResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.ProcessID)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.Channel)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.Payload)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type NotificationResponse struct {
 	fields FieldsNotificationResponse
 }
@@ -379,6 +644,24 @@ func (T *FieldsParameterDescription) Read(payloadLength int, reader io.Reader) (
 	return
 }
 
+func (T *FieldsParameterDescription) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt16(writer, int16(len(T.Parameters)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Parameters {
+		temp, err = WriteInt32(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type ParameterDescription struct {
 	fields FieldsParameterDescription
 }
@@ -400,6 +683,22 @@ func (T *FieldsParameterStatus) Read(payloadLength int, reader io.Reader) (err e
 	return
 }
 
+func (T *FieldsParameterStatus) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Parameter)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.Value)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type ParameterStatus struct {
 	fields FieldsParameterStatus
 }
@@ -411,6 +710,12 @@ func (T *FieldsParseComplete) Read(payloadLength int, reader io.Reader) (err err
 	return
 }
 
+func (T *FieldsParseComplete) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type ParseComplete struct {
 	fields FieldsParseComplete
 }
@@ -422,6 +727,12 @@ func (T *FieldsPortalSuspended) Read(payloadLength int, reader io.Reader) (err e
 	return
 }
 
+func (T *FieldsPortalSuspended) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type PortalSuspended struct {
 	fields FieldsPortalSuspended
 }
@@ -433,6 +744,12 @@ func (T *FieldsReadForQuery) Read(payloadLength int, reader io.Reader) (err erro
 	return
 }
 
+func (T *FieldsReadForQuery) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type ReadForQuery struct {
 	fields FieldsReadForQuery
 }
@@ -479,6 +796,47 @@ func (T *FieldsRowDescriptionFields) Read(payloadLength int, reader io.Reader) (
 	return
 }
 
+func (T *FieldsRowDescriptionFields) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Name)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, T.TableId)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, T.AttributeNumber)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, T.DataType)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, T.DataTypeSize)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, T.TypeModifier)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, T.FormatCode)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type FieldsRowDescription struct {
 	Fields []FieldsRowDescriptionFields
 }
@@ -499,6 +857,24 @@ func (T *FieldsRowDescription) Read(payloadLength int, reader io.Reader) (err er
 	return
 }
 
+func (T *FieldsRowDescription) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt16(writer, int16(len(T.Fields)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Fields {
+		temp, err = v.Write(writer)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type RowDescription struct {
 	fields FieldsRowDescription
 }
diff --git a/lib/gat/protocol/frontend.go b/lib/gat/protocol/frontend.go
index c0fbe97ba8324f8554f9a25f3e368704e4b926bf..d68e68cdcc3c47eb68fa1b84cc65b85f47447d8f 100644
--- a/lib/gat/protocol/frontend.go
+++ b/lib/gat/protocol/frontend.go
@@ -24,6 +24,24 @@ func (T *FieldsBindParameterValues) Read(payloadLength int, reader io.Reader) (e
 	return
 }
 
+func (T *FieldsBindParameterValues) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, int32(len(T.Value)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Value {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type FieldsBind struct {
 	Destination             string
 	PreparedStatement       string
@@ -80,6 +98,58 @@ func (T *FieldsBind) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsBind) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Destination)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.PreparedStatement)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, int16(len(T.FormatCodes)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.FormatCodes {
+		temp, err = WriteInt16(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	temp, err = WriteInt16(writer, int16(len(T.ParameterValues)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.ParameterValues {
+		temp, err = v.Write(writer)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	temp, err = WriteInt16(writer, int16(len(T.ResultColumnFormatCodes)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.ResultColumnFormatCodes {
+		temp, err = WriteInt16(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type Bind struct {
 	fields FieldsBind
 }
@@ -106,6 +176,27 @@ func (T *FieldsCancelRequest) Read(payloadLength int, reader io.Reader) (err err
 	return
 }
 
+func (T *FieldsCancelRequest) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.RequestCode)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, T.ProcessID)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, T.SecretKey)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type CancelRequest struct {
 	fields FieldsCancelRequest
 }
@@ -127,6 +218,22 @@ func (T *FieldsClose) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsClose) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteByte(writer, T.Which)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.Name)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type Close struct {
 	fields FieldsClose
 }
@@ -143,6 +250,17 @@ func (T *FieldsCopyFail) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsCopyFail) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Cause)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type CopyFail struct {
 	fields FieldsCopyFail
 }
@@ -164,6 +282,22 @@ func (T *FieldsDescribe) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsDescribe) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteByte(writer, T.Which)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.Name)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type Describe struct {
 	fields FieldsDescribe
 }
@@ -185,6 +319,22 @@ func (T *FieldsExecute) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsExecute) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Name)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, T.MaxRows)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type Execute struct {
 	fields FieldsExecute
 }
@@ -196,6 +346,12 @@ func (T *FieldsFlush) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsFlush) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type Flush struct {
 	fields FieldsFlush
 }
@@ -220,6 +376,24 @@ func (T *FieldsFunctionCallArguments) Read(payloadLength int, reader io.Reader)
 	return
 }
 
+func (T *FieldsFunctionCallArguments) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, int32(len(T.Value)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Value {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type FieldsFunctionCall struct {
 	Function            int32
 	ArgumentFormatCodes []int16
@@ -263,6 +437,46 @@ func (T *FieldsFunctionCall) Read(payloadLength int, reader io.Reader) (err erro
 	return
 }
 
+func (T *FieldsFunctionCall) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.Function)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt16(writer, int16(len(T.ArgumentFormatCodes)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.ArgumentFormatCodes {
+		temp, err = WriteInt16(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	temp, err = WriteInt16(writer, int16(len(T.Arguments)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.Arguments {
+		temp, err = v.Write(writer)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	temp, err = WriteInt16(writer, T.ResultFormatCode)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type FunctionCall struct {
 	fields FieldsFunctionCall
 }
@@ -279,6 +493,17 @@ func (T *FieldsGSSENCRequest) Read(payloadLength int, reader io.Reader) (err err
 	return
 }
 
+func (T *FieldsGSSENCRequest) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.EncryptionRequestCode)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type GSSENCRequest struct {
 	fields FieldsGSSENCRequest
 }
@@ -299,6 +524,19 @@ func (T *FieldsGSSResponse) Read(payloadLength int, reader io.Reader) (err error
 	return
 }
 
+func (T *FieldsGSSResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	for _, v := range T.Data {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type GSSResponse struct {
 	fields FieldsGSSResponse
 }
@@ -333,6 +571,34 @@ func (T *FieldsParse) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsParse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.PreparedStatement)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.Query)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, int32(len(T.ParameterDataTypes)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.ParameterDataTypes {
+		temp, err = WriteInt32(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type Parse struct {
 	fields FieldsParse
 }
@@ -349,6 +615,17 @@ func (T *FieldsPasswordMessage) Read(payloadLength int, reader io.Reader) (err e
 	return
 }
 
+func (T *FieldsPasswordMessage) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Password)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type PasswordMessage struct {
 	fields FieldsPasswordMessage
 }
@@ -365,6 +642,17 @@ func (T *FieldsQuery) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsQuery) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Query)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type Query struct {
 	fields FieldsQuery
 }
@@ -394,6 +682,29 @@ func (T *FieldsSASLInitialResponse) Read(payloadLength int, reader io.Reader) (e
 	return
 }
 
+func (T *FieldsSASLInitialResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteString(writer, T.Mechanism)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteInt32(writer, int32(len(T.InitialResponse)))
+	if err != nil {
+		return
+	}
+	length += temp
+	for _, v := range T.InitialResponse {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type SASLInitialResponse struct {
 	fields FieldsSASLInitialResponse
 }
@@ -414,6 +725,19 @@ func (T *FieldsSASLResponse) Read(payloadLength int, reader io.Reader) (err erro
 	return
 }
 
+func (T *FieldsSASLResponse) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	for _, v := range T.Data {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type SASLResponse struct {
 	fields FieldsSASLResponse
 }
@@ -430,6 +754,17 @@ func (T *FieldsSSLRequest) Read(payloadLength int, reader io.Reader) (err error)
 	return
 }
 
+func (T *FieldsSSLRequest) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.SSLRequestCode)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type SSLRequest struct {
 	fields FieldsSSLRequest
 }
@@ -456,6 +791,27 @@ func (T *FieldsStartupMessage) Read(payloadLength int, reader io.Reader) (err er
 	return
 }
 
+func (T *FieldsStartupMessage) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	temp, err = WriteInt32(writer, T.ProtocolVersionNumber)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.ParameterName)
+	if err != nil {
+		return
+	}
+	length += temp
+	temp, err = WriteString(writer, T.ParameterValue)
+	if err != nil {
+		return
+	}
+	length += temp
+	_ = temp
+	return
+}
+
 type StartupMessage struct {
 	fields FieldsStartupMessage
 }
@@ -467,6 +823,12 @@ func (T *FieldsSync) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsSync) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type Sync struct {
 	fields FieldsSync
 }
@@ -478,6 +840,12 @@ func (T *FieldsTerminate) Read(payloadLength int, reader io.Reader) (err error)
 	return
 }
 
+func (T *FieldsTerminate) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type Terminate struct {
 	fields FieldsTerminate
 }
diff --git a/lib/gat/protocol/io.go b/lib/gat/protocol/io.go
index a3356ee2a6e166961002ac7524091123b7bb04dd..8254750217adf1751f4b254061ad949231036b5d 100644
--- a/lib/gat/protocol/io.go
+++ b/lib/gat/protocol/io.go
@@ -59,3 +59,56 @@ func ReadString(reader io.Reader) (string, error) {
 	_, err = reader.Read(b[:])
 	return string(b), err
 }
+
+func WriteByte(writer io.Writer, value byte) (int, error) {
+	var b [1]byte
+	b[0] = value
+	return writer.Write(b[:])
+}
+
+func WriteInt8(writer io.Writer, value int8) (int, error) {
+	return WriteByte(writer, byte(value))
+}
+
+func WriteUint16(writer io.Writer, value uint16) (int, error) {
+	var b [2]byte
+	binary.BigEndian.PutUint16(b[:], value)
+	return writer.Write(b[:])
+}
+
+func WriteInt16(writer io.Writer, value int16) (int, error) {
+	return WriteUint16(writer, uint16(value))
+}
+
+func WriteUint32(writer io.Writer, value uint32) (int, error) {
+	var b [4]byte
+	binary.BigEndian.PutUint32(b[:], value)
+	return writer.Write(b[:])
+}
+
+func WriteInt32(writer io.Writer, value int32) (int, error) {
+	return WriteUint32(writer, uint32(value))
+}
+
+func WriteUint64(writer io.Writer, value uint64) (int, error) {
+	var b [8]byte
+	binary.BigEndian.PutUint64(b[:], value)
+	return writer.Write(b[:])
+}
+
+func WriteInt64(writer io.Writer, value int64) (int, error) {
+	return WriteUint64(writer, uint64(value))
+}
+
+func WriteString(writer io.Writer, value string) (int, error) {
+	// TODO i actually have no idea how they format strings, but i'm guessing it's UTF-8 with an int32 length prefix
+	length, err := WriteInt32(writer, int32(len(value)))
+	if err != nil {
+		return 0, err
+	}
+	_, err = writer.Write([]byte(value))
+	if err != nil {
+		return 0, err
+	}
+	return length + len(value), nil
+}
diff --git a/lib/gat/protocol/shared.go b/lib/gat/protocol/shared.go
index b8949867b8954350925b54b3b42f13d25d6b5c58..147a7e71d0156db7286f5bcb6447c9c7204263dc 100644
--- a/lib/gat/protocol/shared.go
+++ b/lib/gat/protocol/shared.go
@@ -20,6 +20,19 @@ func (T *FieldsCopyData) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsCopyData) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	for _, v := range T.Data {
+		temp, err = WriteByte(writer, v)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	_ = temp
+	return
+}
+
 type CopyData struct {
 	fields FieldsCopyData
 }
@@ -31,6 +44,12 @@ func (T *FieldsCopyDone) Read(payloadLength int, reader io.Reader) (err error) {
 	return
 }
 
+func (T *FieldsCopyDone) Write(writer io.Writer) (length int, err error) {
+	var temp int
+	_ = temp
+	return
+}
+
 type CopyDone struct {
 	fields FieldsCopyDone
 }