diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c
index 1575a81b01..7adf16131a 100644
--- a/src/backend/access/heap/heaptoast.c
+++ b/src/backend/access/heap/heaptoast.c
@@ -106,8 +106,10 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 	bool		toast_isnull[MaxHeapAttributeNumber];
 	bool		toast_oldisnull[MaxHeapAttributeNumber];
 	Datum		toast_values[MaxHeapAttributeNumber];
+	Datum		toast_values_copy[MaxHeapAttributeNumber];
 	Datum		toast_oldvalues[MaxHeapAttributeNumber];
 	ToastAttrInfo toast_attr[MaxHeapAttributeNumber];
+	ToastAttrInfo toast_attr_copy[MaxHeapAttributeNumber];
 	ToastTupleContext ttc;
 
 	/*
@@ -176,6 +178,15 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 	/* now convert to a limit on the tuple data size */
 	maxDataLen = RelationGetToastTupleTarget(rel, TOAST_TUPLE_TARGET) - hoff;
 
+	/*
+	 * Preserve references to the original uncompressed data before attempting
+	 * the compression.  So that during externalize if we decide not to store
+	 * the compressed data then we have the original data with us.  For more
+	 * details refer to comments atop toast_tuple_opt_externalize.
+	 */
+	memcpy(toast_attr_copy, toast_attr, sizeof(toast_attr));
+	memcpy(toast_values_copy, toast_values, sizeof(toast_values));
+
 	/*
 	 * Look for attributes with attstorage EXTENDED to compress.  Also find
 	 * large attributes with attstorage EXTENDED or EXTERNAL, and store them
@@ -214,7 +225,9 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 		 */
 		if (toast_attr[biggest_attno].tai_size > maxDataLen &&
 			rel->rd_rel->reltoastrelid != InvalidOid)
-			toast_tuple_externalize(&ttc, biggest_attno, options);
+			toast_tuple_externalize_wrapper(&ttc, biggest_attno, options,
+										toast_values_copy[biggest_attno],
+										&toast_attr_copy[biggest_attno]);
 	}
 
 	/*
@@ -231,7 +244,9 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 		biggest_attno = toast_tuple_find_biggest_attribute(&ttc, false, false);
 		if (biggest_attno < 0)
 			break;
-		toast_tuple_externalize(&ttc, biggest_attno, options);
+		toast_tuple_externalize_wrapper(&ttc, biggest_attno, options,
+									toast_values_copy[biggest_attno],
+									&toast_attr_copy[biggest_attno]);
 	}
 
 	/*
@@ -267,7 +282,9 @@ heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 		if (biggest_attno < 0)
 			break;
 
-		toast_tuple_externalize(&ttc, biggest_attno, options);
+		toast_tuple_externalize_wrapper(&ttc, biggest_attno, options,
+									toast_values_copy[biggest_attno],
+									&toast_attr_copy[biggest_attno]);
 	}
 
 	/*
diff --git a/src/backend/access/table/toast_helper.c b/src/backend/access/table/toast_helper.c
index 0cc5a30f9b..02ec0f2bc4 100644
--- a/src/backend/access/table/toast_helper.c
+++ b/src/backend/access/table/toast_helper.c
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include "access/detoast.h"
+#include "access/heaptoast.h"
 #include "access/table.h"
 #include "access/toast_helper.h"
 #include "access/toast_internals.h"
@@ -235,8 +236,6 @@ toast_tuple_try_compression(ToastTupleContext *ttc, int attribute)
 	if (DatumGetPointer(new_value) != NULL)
 	{
 		/* successful compression */
-		if ((attr->tai_colflags & TOASTCOL_NEEDS_FREE) != 0)
-			pfree(DatumGetPointer(*value));
 		*value = new_value;
 		attr->tai_colflags |= TOASTCOL_NEEDS_FREE;
 		attr->tai_size = VARSIZE(DatumGetPointer(*value));
@@ -252,7 +251,7 @@ toast_tuple_try_compression(ToastTupleContext *ttc, int attribute)
 /*
  * Move an attribute to external storage.
  */
-void
+static void
 toast_tuple_externalize(ToastTupleContext *ttc, int attribute, int options)
 {
 	Datum	   *value = &ttc->ttc_values[attribute];
@@ -268,6 +267,62 @@ toast_tuple_externalize(ToastTupleContext *ttc, int attribute, int options)
 	ttc->ttc_flags |= (TOAST_NEEDS_CHANGE | TOAST_NEEDS_FREE);
 }
 
+/*
+ * Wrapper function for the external TOAST storage.
+ *
+ * TOAST the compressed value only if we are saving at least 1 chunk
+ * (2KB default) of disk storage else use the uncompressed one. In this way, we
+ * will save decompression costs everytime fetching that data without losing
+ * much on storage.
+ */
+void
+toast_tuple_externalize_wrapper(ToastTupleContext *ttc, int attribute, int options,
+							Datum orig_toast_value, ToastAttrInfo *orig_attr)
+{
+	Datum	   *value = &ttc->ttc_values[attribute];
+	ToastAttrInfo *attr = &ttc->ttc_attr[attribute];
+
+	/*
+	 * We are applying this optimization only if the data is compressed
+	 * recently, In the case, data is uncompressed or data was already
+	 * compressed even before TOAST-ing we can proceed as usual.
+	 */
+	if (*value == orig_toast_value)
+		toast_tuple_externalize(ttc, attribute, options);
+	else
+	{
+		/*
+		 * Here we decides whether to store compressed form or not by checking
+		 * if number of chunks is reduced. However we made an exception when
+		 * data size is small.
+		 * Experiments show that we are not gaining much by storing uncompressed
+		 * values where uncompressed form size < 2 * TOAST_MAX_CHUNK_SIZE, in
+		 * some cases we end up using significantly more disk space by storing
+		 * uncompressed data, to avoid this we are going with compressed data
+		 * for such cases.
+		 */
+		if (orig_attr->tai_size < 2 * TOAST_MAX_CHUNK_SIZE ||
+			(attr->tai_size / TOAST_MAX_CHUNK_SIZE <
+			 orig_attr->tai_size / TOAST_MAX_CHUNK_SIZE))
+		{
+			if ((orig_attr->tai_colflags & TOASTCOL_NEEDS_FREE) != 0)
+				pfree(DatumGetPointer(orig_toast_value));
+			toast_tuple_externalize(ttc, attribute, options);
+		}
+		else
+		{
+			/*
+			 * Using the uncompressed data instead, release memory for the
+			 * compressed data.
+			 */
+			pfree(DatumGetPointer(*value));
+			*value = orig_toast_value;
+			*attr = *orig_attr;
+			toast_tuple_externalize(ttc, attribute, options);
+		}
+	}
+}
+
 /*
  * Perform appropriate cleanup after one tuple has been subjected to TOAST.
  */
diff --git a/src/include/access/toast_helper.h b/src/include/access/toast_helper.h
index 1e2aaf3303..2cce8d17b8 100644
--- a/src/include/access/toast_helper.h
+++ b/src/include/access/toast_helper.h
@@ -106,8 +106,10 @@ extern int	toast_tuple_find_biggest_attribute(ToastTupleContext *ttc,
 											   bool for_compression,
 											   bool check_main);
 extern void toast_tuple_try_compression(ToastTupleContext *ttc, int attribute);
-extern void toast_tuple_externalize(ToastTupleContext *ttc, int attribute,
-									int options);
+extern void toast_tuple_externalize_wrapper(ToastTupleContext *ttc,
+											int attribute, int options,
+											Datum old_toast_value,
+											ToastAttrInfo *old_toast_attr);
 extern void toast_tuple_cleanup(ToastTupleContext *ttc);
 
 extern void toast_delete_external(Relation rel, Datum *values, bool *isnull,
