diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 0c60077e1f..cdf07ae5ed 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -183,7 +183,7 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
         <replaceable>init_steps</replaceable> specifies the
         initialization steps to be performed, using one character per step.
         Each step is invoked in the specified order.
-        The default is <literal>dtgvp</literal>.
+        The default is <literal>dtgvpn</literal>.
         The available steps are:
 
         <variablelist>
@@ -256,7 +256,7 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
           </listitem>
          </varlistentry>
          <varlistentry>
-         <term><literal>f</literal> (create Foreign keys)</term>
+          <term><literal>f</literal> (create Foreign keys)</term>
           <listitem>
            <para>
             Create foreign key constraints between the standard tables.
@@ -264,6 +264,15 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
            </para>
           </listitem>
          </varlistentry>
+         <varlistentry>
+          <term><literal>n</literal> (create fuNctioN)</term>
+          <listitem>
+           <para>
+            Create the function versions of the <literal>tpcb-like</literal> transaction,
+            for use with the <literal>tpcb-func</literal> and <literal>tpcb-proc</literal> built-ins.
+           </para>
+          </listitem>
+         </varlistentry>
         </variablelist></para>
       </listitem>
      </varlistentry>
@@ -410,8 +419,8 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
       <listitem>
        <para>
         Add the specified built-in script to the list of scripts to be executed.
-        Available built-in scripts are: <literal>tpcb-like</literal>,
-        <literal>simple-update</literal> and <literal>select-only</literal>.
+        Available built-in scripts are: <literal>tpcb-like</literal>, <literal>tpcb-func</literal>,
+        <literal>tpcb-proc</literal>, <literal>simple-update</literal> and <literal>select-only</literal>.
         Unambiguous prefixes of built-in names are accepted.
         With the special name <literal>list</literal>, show the list of built-in scripts
         and exit immediately.
@@ -975,6 +984,19 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
    <listitem><para><literal>END;</literal></para></listitem>
   </orderedlist>
 
+  <para>
+   If you select the <literal>tpcb-func</literal> built-in,
+   the above steps are carried out by a single call to a <application>PL/pgSQL</application> function,
+   reducing the overhead from inter-process-communication.
+  </para>
+
+  <para>
+   If you select the <literal>tpcb-proc</literal> built-in,
+   the above steps are executed for many iterations iterations in separate transactions by a single call to 
+   a <application>PL/pgSQL</application> procedure,
+   reducing the overhead from inter-process-communication even further.  Requires a PostgreSQL server of version 11 or better.
+  </para>
+
   <para>
    If you select the <literal>simple-update</literal> built-in (also <option>-N</option>),
    steps 4 and 5 aren't included in the transaction.
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 364b5a2e47..0c043deabe 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -168,8 +168,8 @@ typedef struct socket_set
 /********************************************************************
  * some configurable parameters */
 
-#define DEFAULT_INIT_STEPS "dtgvp"	/* default -I setting */
-#define ALL_INIT_STEPS "dtgGvpf"	/* all possible steps */
+#define DEFAULT_INIT_STEPS "dtgvpn"	/* default -I setting */
+#define ALL_INIT_STEPS "dtgGvpfn"	/* all possible steps */
 
 #define LOG_STEP_SECONDS	5	/* seconds between log messages */
 #define DEFAULT_NXACTS	10		/* default nxacts */
@@ -625,6 +625,21 @@ static const BuiltinScript builtin_script[] =
 		"INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
 		"END;\n"
 	},
+	{
+		"tpcb-func",
+		"<builtin: TPC-B (sort of) in PL/pgSQL>",
+		"\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
+		"\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
+		"\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
+		"\\set delta random(-5000, 5000)\n"
+		"select * from pgbench_transaction(:aid, :bid, :tid, :delta);\n"
+	},
+	{
+		"tpcb-proc",
+		"<builtin: TPC-B (sort of) in PL/pgSQL Procedure>",
+		"CALL pgbench_proc("CppAsString2(naccounts) " * :scale, " CppAsString2(ntellers) 
+			" * :scale, " CppAsString2(nbranches) " * :scale, 100);\n"
+	},
 	{
 		"simple-update",
 		"<builtin: simple update>",
@@ -4375,6 +4390,59 @@ initCreateFKeys(PGconn *con)
 	}
 }
 
+/*
+ * Create PL/pgSQL function with standard transaction
+ */
+static void
+initCreateFunctions(PGconn *con)
+{
+	static const char *const DDLFUNCs[] = {
+		"create or replace function pgbench_transaction(arg_aid int, arg_bid int, arg_tid int, arg_delta int) returns int as $$"
+		"DECLARE\n"
+		"abal int;\n"
+		"BEGIN\n"
+		"UPDATE pgbench_accounts SET abalance = abalance + arg_delta WHERE aid = arg_aid;\n"
+		"SELECT abalance into abal FROM pgbench_accounts WHERE aid = arg_aid;\n"
+		"UPDATE pgbench_tellers SET tbalance = tbalance + arg_delta WHERE tid = arg_tid;\n"
+		"UPDATE pgbench_branches SET bbalance = bbalance + arg_delta WHERE bid = arg_bid;\n"
+		"INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (arg_tid, arg_bid, arg_aid, arg_delta, CURRENT_TIMESTAMP);\n"
+		"RETURN abal;\n"
+		"END;\n"
+		"$$ language plpgsql",
+		"CREATE OR REPLACE PROCEDURE public.pgbench_proc(naccounts integer, ntellers integer, nbranches integer, loops integer)\n"
+		" LANGUAGE plpgsql\n"
+		"AS $procedure$ \n"
+		"DECLARE\n"
+		"  account_id int; \n"
+		"  branch_id int; \n"
+		"  teller_id int; \n"
+		"  d int;\n"
+		"  abal int; \n"
+		"BEGIN\n"
+		" FOR x IN 1 .. loops LOOP\n"
+		"   account_id = 1+floor(random()*naccounts); \n"
+		"   branch_id = 1+floor(random()*nbranches); \n"
+		"   teller_id = 1+floor(random()*ntellers); \n"
+		"   d = floor(random()*10000-5000);\n"
+		"   UPDATE pgbench_accounts SET abalance = abalance + d WHERE aid = account_id;\n"
+		"   SELECT abalance into abal FROM pgbench_accounts WHERE aid = account_id;\n"
+		"   UPDATE pgbench_tellers SET tbalance = tbalance + d WHERE tid = teller_id;\n"
+		"   UPDATE pgbench_branches SET bbalance = bbalance + d WHERE bid = branch_id;\n"
+		"   INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (teller_id, branch_id, account_id, d, CURRENT_TIMESTAMP);\n"
+		"   COMMIT;\n"
+		" END LOOP;\n"
+		"END\n"
+		"$procedure$\n"
+	};
+	int			i;
+
+	fprintf(stderr, "creating PL/pgSQL function...\n");
+	for (i = 0; i < lengthof(DDLFUNCs); i++)
+	{
+		executeStatement(con, DDLFUNCs[i]);
+	}
+}
+
 /*
  * Validate an initialization-steps string
  *
@@ -4457,6 +4525,9 @@ runInitSteps(const char *initialize_steps)
 				op = "foreign keys";
 				initCreateFKeys(con);
 				break;
+			case 'n':
+				initCreateFunctions(con);
+				break;
 			case ' ':
 				break;			/* ignore */
 			default:
diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl
index 3aa9d5d753..41c76a9ef2 100644
--- a/src/bin/pgbench/t/001_pgbench_with_server.pl
+++ b/src/bin/pgbench/t/001_pgbench_with_server.pl
@@ -152,7 +152,7 @@ pgbench(
 
 # Run all builtin scripts, for a few transactions each
 pgbench(
-	'--transactions=5 -Dfoo=bla --client=2 --protocol=simple --builtin=t'
+	'--transactions=5 -Dfoo=bla --client=2 --protocol=simple --builtin=tpcb-l'
 	  . ' --connect -n -v -n',
 	0,
 	[
diff --git a/src/bin/pgbench/t/002_pgbench_no_server.pl b/src/bin/pgbench/t/002_pgbench_no_server.pl
index 346a2667fc..e68f4a627a 100644
--- a/src/bin/pgbench/t/002_pgbench_no_server.pl
+++ b/src/bin/pgbench/t/002_pgbench_no_server.pl
@@ -131,7 +131,7 @@ my @options = (
 	],
 	[
 		'weight zero',
-		'-b se@0 -b si@0 -b tpcb@0',
+		'-b se@0 -b si@0 -b tpcb-l@0',
 		[qr{weight must not be zero}]
 	],
 	[ 'init vs run', '-i -S',    [qr{cannot be used in initialization}] ],
