diff --git a/src/test/modules/test_misc/t/004_bug_xact_inprogress.pl b/src/test/modules/test_misc/t/004_bug_xact_inprogress.pl
new file mode 100644
index 0000000000..8a651c0c60
--- /dev/null
+++ b/src/test/modules/test_misc/t/004_bug_xact_inprogress.pl
@@ -0,0 +1,86 @@
+# Test for visibility checks, when an updating transaction has already
+# written commit record but has not yet removed its entry from the
+# proc array, and thus isn't yet visible to other transactions.
+#
+# In particular, this reproduced an old bug in that, see:
+# https://www.postgresql.org/message-id/flat/4da7913d-398c-e2ad-d777-f752cf7f0bbb%40garret.ru
+
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $node = PostgreSQL::Test::Cluster->new('main');
+$node->init(allows_streaming => 1);
+$node->start;
+
+# Create test table
+$node->safe_psql('postgres', 'CREATE TABLE xact_test (t text)');
+$node->safe_psql('postgres', "INSERT INTO xact_test VALUES ('');");
+
+# Launch a psql session in the background that UPDATEs the row and
+# commits, but the COMMIT blocks waiting for synchronous replication.
+#
+# We don't have a replica configured, so it will hang forever.
+$node->safe_psql('postgres',
+				 "ALTER SYSTEM SET synchronous_standby_names = 'nonexistent';");
+$node->reload;
+
+my $in  = '';
+my $out = '';
+my $timeout = IPC::Run::timeout($PostgreSQL::Test::Utils::timeout_default);
+
+my $h = $node->background_psql('postgres', \$in, \$out, $timeout);
+
+# Read current xid, we'll need it later
+$out = '';
+$in = "BEGIN;\n";
+$in .= "show synchronous_standby_names;\n";
+$in .= "SELECT pg_backend_pid(), pg_current_xact_id();\n";
+pump_until($h, $timeout, \$out, qr/([[:digit:]]+)\|([[:digit:]]+)[\r\n]$/m);
+
+$out =~ /([[:digit:]]+)\|([[:digit:]]+)[\r\n]/;
+my ($pid, $xid) = ($1, $2);
+
+# Update and commit. The commit will block, waiting for the synchronous replica (which doesn't
+# exist).
+$in = "UPDATE xact_test SET t = 'first';\n";
+$in .= "COMMIT;\n";
+$h->pump_nb;
+
+# Make sure the COMMIT has progressed to the synchronous replication wait.
+my $wait_query = "SELECT true FROM pg_stat_activity WHERE pid = $pid AND wait_event = 'SyncRep'";
+$node->poll_query_until('postgres', $wait_query)
+  or die "Timed out while waiting for commit to reach SyncRep state";
+
+# Try to UPDATE the same row from another session.
+#
+# This is expected to block, waiting for the first updating transaction to finish.
+my ($ret, $stdout, $stderr) = $node->psql(
+	'postgres',
+	qq{
+\\set ECHO all
+SET lock_timeout=1;
+
+-- Prime the single-element CLOG lookup cache. (We used to have a bug where the
+-- single-element cache was used incorrectly in the visibility check)
+SELECT pg_xact_status(xid8 '$xid');
+
+-- This is expected to fail due to the lock timeout
+BEGIN;
+UPDATE xact_test SET t = t || ' second';
+
+-- Not reached, because the UPDATE should fail
+SELECT * from xact_test;
+ROLLBACK;
+});
+print "#### Begin standard output\n";
+print $stdout;
+print "\n#### End standard output\n";
+like($stderr, qr/canceling statement due to lock timeout/, "UPDATE fails due to lock timeout");
+
+$node->stop;
+$h->finish;
+
+done_testing();
