diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 72395a50b8..e5c651b498 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2509,6 +2509,18 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 
 	MarkBufferDirty(buffer);
 
+	/*
+	 * Bulk insertion is not safe after a WAL-logging insertion in the same
+	 * transaction. We don't start bulk insertion under inhibitin conditions
+	 * but we also need to cancel WAL-skipping in the case where WAL-logging
+	 * insertion happens during a bulk insertion. This happens by anything
+	 * that can insert a tuple during bulk insertion such like triggers,
+	 * constraints or type conversions. We need not worry about relcache flush
+	 * happening while a bulk insertion is running.
+	 */
+	if (relation->last_logged_insert_xid == xid)
+		options &= ~HEAP_INSERT_SKIP_WAL;
+
 	/* XLOG stuff */
 	if (!(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation))
 	{
@@ -2582,6 +2594,12 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 		recptr = XLogInsert(RM_HEAP_ID, info);
 
 		PageSetLSN(page, recptr);
+
+		/*
+		 * If this happens during a bulk insertion, stop WAL skipping for the
+		 * rest of the current command.
+		 */
+		relation->last_logged_insert_xid = xid;
 	}
 
 	END_CRIT_SECTION();
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 7674369613..7b9a7af2d2 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2416,10 +2416,8 @@ CopyFrom(CopyState cstate)
 	{
 		hi_options |= HEAP_INSERT_SKIP_FSM;
 
-		if (!XLogIsNeeded() &&
-			cstate->rel->trigdesc == NULL &&
-			RelationGetNumberOfBlocks(cstate->rel) == 0)
-			hi_options |= HEAP_INSERT_SKIP_WAL;
+		if (!XLogIsNeeded() && RelationGetNumberOfBlocks(cstate->rel) == 0)
+ 			hi_options |= HEAP_INSERT_SKIP_WAL;
 	}
 
 	/*
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 30a956822f..34a692a497 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1575,6 +1575,9 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
 		{
 			/* Immediate, non-rollbackable truncation is OK */
 			heap_truncate_one_rel(rel);
+
+			/* Allow bulk-insert */
+			rel->last_logged_insert_xid = InvalidTransactionId;
 		}
 		else
 		{
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 6125421d39..99fb7e1dd8 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1243,6 +1243,8 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 	/* It's fully valid */
 	relation->rd_isvalid = true;
 
+	relation->last_logged_insert_xid = InvalidTransactionId;
+
 	return relation;
 }
 
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index c97f9d1b43..6ee575ad14 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -188,6 +188,9 @@ typedef struct RelationData
 
 	/* use "struct" here to avoid needing to include pgstat.h: */
 	struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
+
+	/* XID of the last transaction on which WAL-logged insertion happened */
+	TransactionId		last_logged_insert_xid;
 } RelationData;
 
 
