diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml
index ef7cff4..1c67e97 100644
--- a/doc/src/sgml/xaggr.sgml
+++ b/doc/src/sgml/xaggr.sgml
@@ -511,6 +511,82 @@ SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY income) FROM households;
 
  </sect2>
 
+  <sect2 id="xaggr-partial-aggregates">
+  <title>Partial Aggregates</title>
+
+  <indexterm>
+   <primary>aggregate function</primary>
+   <secondary>partial aggregates</secondary>
+  </indexterm>
+
+  <para>
+  An aggregate function may also optionally support partial mode which will
+  allow the aggregate to participate in optimizations such as parallel
+  aggregation. Supporting aggregate must have a <literal>combinefn</>
+  set. This will allow <productname>PostgreSQL</productname> to combine
+  multiple separately aggregated states into a single state allowing any
+  <literal>finalfn</> to be called upon the resulting states.
+  </para>
+  
+  <para>
+  The <literal>combinefn</> must take two <literal>stype</> arguments and
+  return another <literal>stype</> value which is each of the input values
+  "added" together. For aggregates such as <function>avg</> the
+  <literal>stype</> would track both the sum of the input values and the count
+  of the non-null input values. In this case the <literal>combinefn</> would
+  simply add both sums together and also add both non-null counts together and
+  return the result.
+  </para>
+  
+  <para>
+  For <literal>combinefn</> written in C the resulting aggregate state must
+  be allocated in the aggregate function's memory context. When one of the
+  input states is <literal>NULL</> it's invalid to simply return the other
+  non-null state as these input states will be allocated in the incorrect
+  memory context.
+  </para>
+  
+  <para>
+  For aggregates with an <literal>INTERNAL</> <literal>stype</>, some usages of
+  partial aggregation require that the aggregate function also have a
+  <literal>serialfn</> and <literal>deserialfn</>. This is the case for
+  parallel aggregation, as the resulting states must be transferred from the
+  parallel worker process into the main process, and this is simply not
+  possible to do just by passing the memory address of the
+  <literal>INTERNAL</> state. Instead these states must be serialized into a
+  <literal>serialtype</> by the <literal>serialfn</> to allow the state to be
+  copied between the processes.
+  </para>
+  
+  <para>
+  A <literal>serialfn</> should take a single <literal>INTERNAL</> argument
+  and return a value of <literal>serialtype</>. It's this value that the
+  <literal>deserialfn</> must accept to perform the reverse operation and
+  produce the equivalent <literal>INTERNAL</> state as the one which was
+  passed to the <literal>serialfn</>. The <literal>deserialfn</> must take
+  two parameters, the first of which must be of type <literal>serialtype</>
+  and the second must be of type <literal>INTERNAL</>. The
+  <literal>INTERNAL</> value is a "dummy" value and serves no purpose other
+  than to get around the fact that <productname>PostgreSQL</productname>
+  disallows the creation of functions which return an <literal>INTERNAL</>
+  type but do not take any <literal>INTERNAL</> arguments. This value will
+  always be passed to the <literal>deserialfn</> as <literal>NULL</>. The
+  <literal>deserialfn</> must return a value of type <literal>INTERNAL</>.
+  </para>
+
+<programlisting>
+CREATE AGGREGATE myavg (numeric)
+(
+    stype = internal,
+    sfunc = numeric_avg_accum,
+    finalfunc = numeric_avg,
+    serialtype = bytea,
+    serialfunc = numeric_avg_serialize,
+    deserialfunc = numeric_avg_deserialize,
+    combinefunc = numeric_avg_combine
+);
+</programlisting>
+
  <sect2 id="xaggr-support-functions">
   <title>Support Functions for Aggregates</title>
 
