diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 0a723f0dfa1b4b01fc189a0a09ef3661bb137b2c..7b9e8c1b6fa67b530e3013ec8365a670a75916b7 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -326,9 +326,10 @@ configure_remote_session(PGconn *conn)
 	 * anyway.	However it makes the regression test outputs more predictable.
 	 *
 	 * We don't risk setting remote zone equal to ours, since the remote
-	 * server might use a different timezone database.
+	 * server might use a different timezone database.  Instead, use UTC
+	 * (quoted, because very old servers are picky about case).
 	 */
-	do_sql_command(conn, "SET timezone = UTC");
+	do_sql_command(conn, "SET timezone = 'UTC'");
 
 	/*
 	 * Set values needed to ensure unambiguous data output from remote.  (This
@@ -542,8 +543,14 @@ pgfdw_xact_callback(XactEvent event, void *arg)
 				 * prepared statements, do a DEALLOCATE ALL to make sure we
 				 * get rid of all prepared statements.	This is annoying and
 				 * not terribly bulletproof, but it's probably not worth
-				 * trying harder.  We intentionally ignore any errors in the
-				 * DEALLOCATE.
+				 * trying harder.
+				 *
+				 * DEALLOCATE ALL only exists in 8.3 and later, so this
+				 * constrains how old a server postgres_fdw can communicate
+				 * with.  We intentionally ignore errors in the DEALLOCATE, so
+				 * that we can hobble along to some extent with older servers
+				 * (leaking prepared statements as we go; but we don't really
+				 * support update operations pre-8.3 anyway).
 				 */
 				if (entry->have_prep_stmt && entry->have_error)
 				{
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 687b87b8604bb03efc22c7ed5a79db5d9f3e97a6..49dfe2c5edb0f480c36d622c15fae3b83cb4d432 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -801,6 +801,9 @@ postgresGetForeignPlan(PlannerInfo *root,
 	 * The extra roundtrips involved in trying to duplicate the local
 	 * semantics exactly don't seem worthwhile (see also comments for
 	 * RowMarkType).
+	 *
+	 * Note: because we actually run the query as a cursor, this assumes that
+	 * DECLARE CURSOR ... FOR UPDATE is supported, which it isn't before 8.3.
 	 */
 	if (baserel->relid == root->parse->resultRelation &&
 		(root->parse->commandType == CMD_UPDATE ||
diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml
index 61cc2aafc2480ad9f955de6804003c3699c998e3..4aa798ac2ee820aa36aab91a549427138db8d09b 100644
--- a/doc/src/sgml/postgres-fdw.sgml
+++ b/doc/src/sgml/postgres-fdw.sgml
@@ -318,6 +318,26 @@
   </para>
  </sect2>
 
+ <sect2>
+  <title>Cross-Version Compatibility</title>
+
+  <para>
+   <filename>postgres_fdw</> can be used with remote servers dating back
+   to <productname>PostgreSQL</> 8.3.  Read-only capability is available
+   back to 8.1.  A limitation however is that <filename>postgres_fdw</>
+   generally assumes that immutable built-in functions and operators are
+   safe to send to the remote server for execution, if they appear in a
+   <literal>WHERE</> clause for a foreign table.  Thus, a built-in
+   function that was added since the remote server's release might be sent
+   to it for execution, resulting in <quote>function does not exist</> or
+   a similar error.  This type of failure can be worked around by
+   rewriting the query, for example by embedding the foreign table
+   reference in a sub-<literal>SELECT</> with <literal>OFFSET 0</> as an
+   optimization fence, and placing the problematic function or operator
+   outside the sub-<literal>SELECT</>.
+  </para>
+ </sect2>
+
  <sect2>
   <title>Author</title>
   <para>