diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 697cf40..57d1694 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -158,6 +158,19 @@ SET ENABLE_SEQSCAN TO OFF;
      require superuser permission to change via <command>SET</command> or
      <command>ALTER</>.
     </para>
+
+    <para>
+     Another way to change configuration parameters persistently is by
+     use of <xref linkend="SQL-ALTERSYSTEM">
+     command, for example:
+<screen>
+ALTER SYSTEM SET checkpoint_timeout TO 600;
+</screen>
+     This command will allow users to change values persistently
+     through SQL command. The values will be effective after reload of server configuration
+     (<acronym>SIGHUP</>) or server startup. The effect of this command is similar to when
+     user manually changes values in <filename>postgresql.conf</filename>.
+    </para>
    </sect2>
 
    <sect2 id="config-setting-examining">
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 5846974..ce7a5e3 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -30,6 +30,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY alterSchema        SYSTEM "alter_schema.sgml">
 <!ENTITY alterServer        SYSTEM "alter_server.sgml">
 <!ENTITY alterSequence      SYSTEM "alter_sequence.sgml">
+<!ENTITY alterSystem        SYSTEM "alter_system.sgml">
 <!ENTITY alterTable         SYSTEM "alter_table.sgml">
 <!ENTITY alterTableSpace    SYSTEM "alter_tablespace.sgml">
 <!ENTITY alterTSConfig      SYSTEM "alter_tsconfig.sgml">
diff --git a/doc/src/sgml/ref/alter_system.sgml b/doc/src/sgml/ref/alter_system.sgml
new file mode 100644
index 0000000..3ccc6af
--- /dev/null
+++ b/doc/src/sgml/ref/alter_system.sgml
@@ -0,0 +1,114 @@
+<!--
+doc/src/sgml/ref/alter_system.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERSYSTEM">
+ <refmeta>
+  <refentrytitle>ALTER SYSTEM</refentrytitle>
+  <manvolnum>7</manvolnum>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>ALTER SYSTEM</refname>
+  <refpurpose>change a server configuration parameter</refpurpose>
+ </refnamediv>
+
+ <indexterm zone="sql-altersystem">
+  <primary>ALTER SYSTEM</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER SYSTEM SET <replaceable class="PARAMETER">configuration_parameter</replaceable> { TO | = } { <replaceable class="PARAMETER">value</replaceable> | '<replaceable class="PARAMETER">value</replaceable>' | DEFAULT }
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>ALTER SYSTEM</command> writes the configuration parameter
+   values to the <filename>postgresql.auto.conf</filename> file. With
+   <literal>DEFAULT</literal>, it removes a configuration entry from
+   <filename>postgresql.auto.conf</filename> file. The values will be
+   effective after reload of server configuration (SIGHUP) or in next 
+   server start based on the type of configuration parameter modified.
+  </para>
+
+  <para>
+   This command is not allowed inside transaction block or function.
+  </para>
+  
+  <para>
+   See <xref linkend="config-setting"> for other ways to set the parameters and 
+   how they become effective.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Parameters</title>
+
+  <variablelist>
+   <varlistentry>
+    <term><replaceable class="parameter">configuration_parameter</replaceable></term>
+    <listitem>
+     <para>
+      Name of a settable run-time parameter.  Available parameters are
+      documented in <xref linkend="runtime-config">.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">value</replaceable></term>
+    <listitem>
+     <para>
+      New value of parameter.  Values can be specified as string
+      constants, identifiers, numbers, or comma-separated lists of
+      these, as appropriate for the particular parameter.
+      <literal>DEFAULT</literal> can be written to specify to remove the
+      parameter and its value from <filename>postgresql.auto.conf</filename>
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </refsect1>
+
+ <refsect1>
+  <title>Examples</title>
+
+  <para>
+   Set the <literal>wal_level</>:
+<programlisting>
+ALTER SYSTEM SET wal_level = hot_standby;
+</programlisting>
+  </para>
+
+  <para>
+   Set the <literal>authentication_timeout</>:
+<programlisting>
+ALTER SYSTEM SET authentication_timeout = 10;
+</programlisting></para>
+ </refsect1>
+
+ <refsect1>
+  <title>Compatibility</title>
+
+  <para>
+   The <command>ALTER SYSTEM</command> statement is a
+   <productname>PostgreSQL</productname> extension.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="SQL-SET"></member>
+   <member><xref linkend="SQL-SHOW"></member>
+  </simplelist>
+ </refsect1>
+
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 14e217a..85d0c7b 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -58,6 +58,7 @@
    &alterSchema;
    &alterSequence;
    &alterServer;
+   &alterSystem;
    &alterTable;
    &alterTableSpace;
    &alterTSConfig;
diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml
index e0a93c1..1b9999c 100644
--- a/doc/src/sgml/storage.sgml
+++ b/doc/src/sgml/storage.sgml
@@ -120,6 +120,12 @@ Item
 </row>
 
 <row>
+ <entry><filename>postgresql.auto.conf</></entry>
+ <entry>A file used for storing configuration parameters that are set by
+<command>ALTER SYSTEM</command></entry>
+</row>
+
+<row>
  <entry><filename>postmaster.opts</></entry>
  <entry>A file recording the command-line options the server was
 last started with</entry>
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 65f3b98..9f1c7c3 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3270,6 +3270,16 @@ _copyRefreshMatViewStmt(const RefreshMatViewStmt *from)
 	return newnode;
 }
 
+static AlterSystemStmt *
+_copyAlterSystemStmt(const AlterSystemStmt * from)
+{
+	AlterSystemStmt *newnode = makeNode(AlterSystemStmt);
+
+	COPY_NODE_FIELD(setstmt);
+
+	return newnode;
+}
+
 static CreateSeqStmt *
 _copyCreateSeqStmt(const CreateSeqStmt *from)
 {
@@ -4343,6 +4353,9 @@ copyObject(const void *from)
 		case T_RefreshMatViewStmt:
 			retval = _copyRefreshMatViewStmt(from);
 			break;
+		case T_AlterSystemStmt:
+			retval = _copyAlterSystemStmt(from);
+			break;
 		case T_CreateSeqStmt:
 			retval = _copyCreateSeqStmt(from);
 			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 4c9b05e..61405c2 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1538,6 +1538,15 @@ _equalRefreshMatViewStmt(const RefreshMatViewStmt *a, const RefreshMatViewStmt *
 }
 
 static bool
+_equalAlterSystemStmt(const AlterSystemStmt * a, const AlterSystemStmt * b)
+{
+	COMPARE_NODE_FIELD(setstmt);
+
+	return true;
+}
+
+
+static bool
 _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b)
 {
 	COMPARE_NODE_FIELD(sequence);
@@ -2813,6 +2822,9 @@ equal(const void *a, const void *b)
 		case T_RefreshMatViewStmt:
 			retval = _equalRefreshMatViewStmt(a, b);
 			break;
+		case T_AlterSystemStmt:
+			retval = _equalAlterSystemStmt(a, b);
+			break;
 		case T_CreateSeqStmt:
 			retval = _equalCreateSeqStmt(a, b);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a9812af..dc73063 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -216,7 +216,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 		AlterEventTrigStmt
 		AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
 		AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
-		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
+		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
 		AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
 		AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
 		AlterRoleStmt AlterRoleSetStmt
@@ -396,7 +396,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 %type <istmt>	insert_rest
 
-%type <vsetstmt> set_rest set_rest_more SetResetClause FunctionSetResetClause
+%type <vsetstmt> generic_set set_rest set_rest_more SetResetClause FunctionSetResetClause
 
 %type <node>	TableElement TypedTableElement ConstraintElem TableFuncElement
 %type <node>	columnDef columnOptions
@@ -720,6 +720,7 @@ stmt :
 			| AlterObjectSchemaStmt
 			| AlterOwnerStmt
 			| AlterSeqStmt
+			| AlterSystemStmt
 			| AlterTableStmt
 			| AlterCompositeTypeStmt
 			| AlterRoleSetStmt
@@ -1329,7 +1330,7 @@ set_rest:
 			| set_rest_more
 			;
 
-set_rest_more:	/* Generic SET syntaxes: */
+generic_set:
 			var_name TO var_list
 				{
 					VariableSetStmt *n = makeNode(VariableSetStmt);
@@ -1360,6 +1361,9 @@ set_rest_more:	/* Generic SET syntaxes: */
 					n->name = $1;
 					$$ = n;
 				}
+
+set_rest_more:	/* Generic SET syntaxes: */
+			generic_set 						{$$ = $1;}
 			| var_name FROM CURRENT_P
 				{
 					VariableSetStmt *n = makeNode(VariableSetStmt);
@@ -8261,6 +8265,23 @@ DropdbStmt: DROP DATABASE database_name
 
 /*****************************************************************************
  *
+ *		ALTER SYSTEM SET
+ *
+ * Command to edit postgresql.conf
+ *****************************************************************************/
+
+AlterSystemStmt:
+			ALTER SYSTEM_P SET generic_set
+				{
+					AlterSystemStmt *n = makeNode(AlterSystemStmt);
+					n->setstmt = $4;
+					$$ = (Node *)n;
+				}
+		;
+
+
+/*****************************************************************************
+ *
  * Manipulate a domain
  *
  *****************************************************************************/
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index ba8d173..244e3b0 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -811,6 +811,13 @@ sendDir(char *path, int basepathlen, bool sizeonly)
 					strlen(PG_TEMP_FILE_PREFIX)) == 0)
 			continue;
 
+		/* skip auto conf temporary file */
+		if (strncmp(de->d_name,
+					PG_AUTOCONF_FILENAME ".temp",
+					sizeof(PG_AUTOCONF_FILENAME) + 4) == 0)
+			continue;
+
+
 		/*
 		 * If there's a backup_label file, it belongs to a backup started by
 		 * the user with pg_start_backup(). It is *not* correct for this
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index b1023c4..6c2b705 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -687,6 +687,11 @@ standard_ProcessUtility(Node *parsetree,
 			ExplainQuery((ExplainStmt *) parsetree, queryString, params, dest);
 			break;
 
+		case T_AlterSystemStmt:
+			PreventTransactionChain(isTopLevel, "ALTER SYSTEM");
+			AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
+			break;
+
 		case T_VariableSetStmt:
 			ExecSetVariableStmt((VariableSetStmt *) parsetree);
 			break;
@@ -2156,6 +2161,10 @@ CreateCommandTag(Node *parsetree)
 			tag = "REFRESH MATERIALIZED VIEW";
 			break;
 
+		case T_AlterSystemStmt:
+			tag = "ALTER SYSTEM";
+			break;
+
 		case T_VariableSetStmt:
 			switch (((VariableSetStmt *) parsetree)->kind)
 			{
@@ -2722,6 +2731,10 @@ GetCommandLogLevel(Node *parsetree)
 			lev = LOGSTMT_DDL;
 			break;
 
+		case T_AlterSystemStmt:
+			lev = LOGSTMT_ALL;
+			break;
+
 		case T_VariableSetStmt:
 			lev = LOGSTMT_ALL;
 			break;
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index b730a12..da9d9d6 100644
--- a/src/backend/utils/misc/guc-file.l
+++ b/src/backend/utils/misc/guc-file.l
@@ -120,6 +120,9 @@ ProcessConfigFile(GucContext context)
 				   *head,
 				   *tail;
 	int			i;
+	char		ConfigAutoFileName[MAXPGPATH];
+	char		   *ErrorConfFile;
+	char		*CallingFileName;
 
 	/*
 	 * Config files are processed on startup (by the postmaster only)
@@ -134,6 +137,8 @@ ProcessConfigFile(GucContext context)
 	 */
 	elevel = IsUnderPostmaster ? DEBUG2 : LOG;
 
+	ErrorConfFile = ConfigFileName;
+
 	/* Parse the file into a list of option names and values */
 	head = tail = NULL;
 
@@ -145,6 +150,26 @@ ProcessConfigFile(GucContext context)
 	}
 
 	/*
+	 * Parse postgresql.auto.conf file after postgresql.conf to replace
+	 * parameters set by ALTER SYSTEM command. This file is present in
+	 * data directory, however when called during initdb data directory is not
+	 * set till this point, so use ConfigFile path which will be same.
+	 */
+	snprintf(ConfigAutoFileName,sizeof(ConfigAutoFileName),"%s", PG_AUTOCONF_FILENAME);
+	if (data_directory)
+		CallingFileName = NULL;
+	else
+		CallingFileName = ConfigFileName;
+
+	if (!ParseConfigFile(ConfigAutoFileName, CallingFileName, false, 0, elevel, &head, &tail))
+	{
+		/* Syntax error(s) detected in the file, so bail out */
+		error = true;
+		ErrorConfFile = ConfigAutoFileName;
+		goto cleanup_list;
+	}
+
+	/*
 	 * Mark all extant GUC variables as not present in the config file.
 	 * We need this so that we can tell below which ones have been removed
 	 * from the file since we last processed it.
@@ -348,17 +373,17 @@ ProcessConfigFile(GucContext context)
 			ereport(ERROR,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("configuration file \"%s\" contains errors",
-							ConfigFileName)));
+							ErrorConfFile)));
 		else if (apply)
 			ereport(elevel,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("configuration file \"%s\" contains errors; unaffected changes were applied",
-							ConfigFileName)));
+							ErrorConfFile)));
 		else
 			ereport(elevel,
 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 					 errmsg("configuration file \"%s\" contains errors; no changes were applied",
-							ConfigFileName)));
+							ErrorConfFile)));
 	}
 }
 
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 3107f9c..842ba99 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -57,12 +57,14 @@
 #include "postmaster/postmaster.h"
 #include "postmaster/syslogger.h"
 #include "postmaster/walwriter.h"
+#include "port.h"
 #include "replication/syncrep.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
 #include "storage/bufmgr.h"
 #include "storage/standby.h"
 #include "storage/fd.h"
+#include "storage/lwlock.h"
 #include "storage/proc.h"
 #include "storage/predicate.h"
 #include "tcop/tcopprot.h"
@@ -204,6 +206,10 @@ static char *config_enum_get_options(struct config_enum * record,
 						const char *prefix, const char *suffix,
 						const char *separator);
 
+static int validate_conf_option(struct config_generic * record,
+					 const char *name, const char *value, int elevel,
+					 bool freemem, void *newval, void **newextra);
+
 
 /*
  * Options for enum values defined in this module.
@@ -3424,6 +3430,9 @@ static void ShowAllGUCConfig(DestReceiver *dest);
 static char *_ShowOption(struct config_generic * record, bool use_units);
 static bool validate_option_array_item(const char *name, const char *value,
 						   bool skipIfNoPermissions);
+static void write_auto_conf_file(int fd, const char *filename, ConfigVariable **head_p);
+static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
+						  char *config_file, char *name, char *value);
 
 
 /*
@@ -5186,6 +5195,220 @@ config_enum_get_options(struct config_enum * record, const char *prefix,
 	return retstr.data;
 }
 
+/*
+ * Validates configuration parameter and value, by calling check hook functions
+ * depending on record's vartype. It validates if the parameter
+ * value given is in range of expected predefined value for that parameter.
+ *
+ * freemem - true indicates memory for newval and newextra will be
+ *			 freed in this function, false indicates it will be freed
+ *			 by caller.
+ * Return value:
+ *	1: the value is valid
+ *	0: the name or value is invalid
+ */
+int
+validate_conf_option(struct config_generic * record,
+					 const char *name, const char *value, int elevel,
+					 bool freemem, void *newval, void **newextra)
+{
+	/*
+	 * Validate the value for the passed record, to ensure it is in expected
+	 * range.
+	 */
+	switch (record->vartype)
+	{
+
+		case PGC_BOOL:
+			{
+				struct config_bool *conf = (struct config_bool *) record;
+				bool		tmpnewval;
+
+				if (newval == NULL)
+					newval = &tmpnewval;
+
+				if (value != NULL)
+				{
+					if (!parse_bool(value, newval))
+					{
+						ereport(elevel,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("parameter \"%s\" requires a Boolean value",
+								 name)));
+						return 0;
+					}
+
+					if (!call_bool_check_hook(conf, newval, newextra,
+											  PGC_S_FILE, elevel))
+						return 0;
+
+					if (*newextra && freemem)
+						free(*newextra);
+				}
+			}
+			break;
+		case PGC_INT:
+			{
+				struct config_int *conf = (struct config_int *) record;
+				int			tmpnewval;
+
+				if (newval == NULL)
+					newval = &tmpnewval;
+
+				if (value != NULL)
+				{
+					const char *hintmsg;
+
+					if (!parse_int(value, newval, conf->gen.flags, &hintmsg))
+					{
+						ereport(elevel,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("invalid value for parameter \"%s\": \"%s\"",
+								 name, value),
+								 hintmsg ? errhint("%s", _(hintmsg)) : 0));
+						return 0;
+					}
+
+					if (*((int *) newval) < conf->min || *((int *) newval) > conf->max)
+					{
+						ereport(elevel,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
+										*((int *) newval), name, conf->min, conf->max)));
+						return 0;
+					}
+
+					if (!call_int_check_hook(conf, newval, newextra,
+											 PGC_S_FILE, elevel))
+						return 0;
+
+					if (*newextra && freemem)
+						free(*newextra);
+				}
+			}
+			break;
+		case PGC_REAL:
+			{
+				struct config_real *conf = (struct config_real *) record;
+				double		tmpnewval;
+
+				if (newval == NULL)
+					newval = &tmpnewval;
+
+				if (value != NULL)
+				{
+					if (!parse_real(value, newval))
+					{
+						ereport(elevel,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("parameter \"%s\" requires a numeric value",
+								 name)));
+						return 0;
+					}
+
+					if (*((double *) newval) < conf->min || *((double *) newval) > conf->max)
+					{
+						ereport(elevel,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
+										*((double *) newval), name, conf->min, conf->max)));
+						return 0;
+					}
+
+					if (!call_real_check_hook(conf, newval, newextra,
+											  PGC_S_FILE, elevel))
+						return 0;
+
+					if (*newextra && freemem)
+						free(*newextra);
+				}
+			}
+			break;
+		case PGC_STRING:
+			{
+				struct config_string *conf = (struct config_string *) record;
+				char	   *tempPtr;
+				char	  **tmpnewval = newval;
+
+				if (newval == NULL)
+					tmpnewval = &tempPtr;
+
+				if (value != NULL)
+				{
+					/*
+					 * The value passed by the caller could be transient, so
+					 * we always strdup it.
+					 */
+					*tmpnewval = guc_strdup(elevel, value);
+					if (*tmpnewval == NULL)
+						return 0;
+
+					/*
+					 * The only built-in "parsing" check we have is to apply
+					 * truncation if GUC_IS_NAME.
+					 */
+					if (conf->gen.flags & GUC_IS_NAME)
+						truncate_identifier(*tmpnewval, strlen(*tmpnewval), true);
+
+					if (!call_string_check_hook(conf, tmpnewval, newextra,
+												PGC_S_FILE, elevel))
+					{
+						free(*tmpnewval);
+						return 0;
+					}
+
+					/* Free the malloc'd data if any */
+					if (freemem)
+					{
+						if (*tmpnewval != NULL)
+							free(*tmpnewval);
+						if (*newextra != NULL)
+							free(*newextra);
+					}
+				}
+			}
+			break;
+		case PGC_ENUM:
+			{
+				struct config_enum *conf = (struct config_enum *) record;
+				int			tmpnewval;
+
+				if (newval == NULL)
+					newval = &tmpnewval;
+
+				if (value != NULL)
+				{
+					if (!config_enum_lookup_by_name(conf, value, newval))
+					{
+						char	   *hintmsg;
+
+						hintmsg = config_enum_get_options(conf,
+														"Available values: ",
+														  ".", ", ");
+
+						ereport(ERROR,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("invalid value for parameter \"%s\": \"%s\"",
+										name, value),
+										hintmsg ? errhint("%s", _(hintmsg)) : 0));
+
+						if (hintmsg != NULL)
+							pfree(hintmsg);
+						return 0;
+					}
+					if (!call_enum_check_hook(conf, newval, newextra,
+											  PGC_S_FILE, LOG))
+						return 0;
+
+					if (*newextra && freemem)
+						free(*newextra);
+				}
+			}
+			break;
+	}
+	return 1;
+}
+
 
 /*
  * Sets option `name' to given value.
@@ -5434,16 +5657,8 @@ set_config_option(const char *name, const char *value,
 
 				if (value)
 				{
-					if (!parse_bool(value, &newval))
-					{
-						ereport(elevel,
-								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						  errmsg("parameter \"%s\" requires a Boolean value",
-								 name)));
-						return 0;
-					}
-					if (!call_bool_check_hook(conf, &newval, &newextra,
-											  source, elevel))
+					if (!validate_conf_option(record, name, value, elevel,
+											  false, &newval, &newextra))
 						return 0;
 				}
 				else if (source == PGC_S_DEFAULT)
@@ -5527,27 +5742,8 @@ set_config_option(const char *name, const char *value,
 
 				if (value)
 				{
-					const char *hintmsg;
-
-					if (!parse_int(value, &newval, conf->gen.flags, &hintmsg))
-					{
-						ereport(elevel,
-								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						 errmsg("invalid value for parameter \"%s\": \"%s\"",
-								name, value),
-								 hintmsg ? errhint("%s", _(hintmsg)) : 0));
-						return 0;
-					}
-					if (newval < conf->min || newval > conf->max)
-					{
-						ereport(elevel,
-								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-								 errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
-										newval, name, conf->min, conf->max)));
-						return 0;
-					}
-					if (!call_int_check_hook(conf, &newval, &newextra,
-											 source, elevel))
+					if (!validate_conf_option(record, name, value, elevel,
+											  false, &newval, &newextra))
 						return 0;
 				}
 				else if (source == PGC_S_DEFAULT)
@@ -5631,24 +5827,8 @@ set_config_option(const char *name, const char *value,
 
 				if (value)
 				{
-					if (!parse_real(value, &newval))
-					{
-						ereport(elevel,
-								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						  errmsg("parameter \"%s\" requires a numeric value",
-								 name)));
-						return 0;
-					}
-					if (newval < conf->min || newval > conf->max)
-					{
-						ereport(elevel,
-								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-								 errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
-										newval, name, conf->min, conf->max)));
-						return 0;
-					}
-					if (!call_real_check_hook(conf, &newval, &newextra,
-											  source, elevel))
+					if (!validate_conf_option(record, name, value, elevel,
+											  false, &newval, &newextra))
 						return 0;
 				}
 				else if (source == PGC_S_DEFAULT)
@@ -5732,27 +5912,9 @@ set_config_option(const char *name, const char *value,
 
 				if (value)
 				{
-					/*
-					 * The value passed by the caller could be transient, so
-					 * we always strdup it.
-					 */
-					newval = guc_strdup(elevel, value);
-					if (newval == NULL)
-						return 0;
-
-					/*
-					 * The only built-in "parsing" check we have is to apply
-					 * truncation if GUC_IS_NAME.
-					 */
-					if (conf->gen.flags & GUC_IS_NAME)
-						truncate_identifier(newval, strlen(newval), true);
-
-					if (!call_string_check_hook(conf, &newval, &newextra,
-												source, elevel))
-					{
-						free(newval);
+					if (!validate_conf_option(record, name, value, elevel,
+											  false, &newval, &newextra))
 						return 0;
-					}
 				}
 				else if (source == PGC_S_DEFAULT)
 				{
@@ -5858,26 +6020,8 @@ set_config_option(const char *name, const char *value,
 
 				if (value)
 				{
-					if (!config_enum_lookup_by_name(conf, value, &newval))
-					{
-						char	   *hintmsg;
-
-						hintmsg = config_enum_get_options(conf,
-														"Available values: ",
-														  ".", ", ");
-
-						ereport(elevel,
-								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						 errmsg("invalid value for parameter \"%s\": \"%s\"",
-								name, value),
-								 hintmsg ? errhint("%s", _(hintmsg)) : 0));
-
-						if (hintmsg)
-							pfree(hintmsg);
-						return 0;
-					}
-					if (!call_enum_check_hook(conf, &newval, &newextra,
-											  source, elevel))
+					if (!validate_conf_option(record, name, value, elevel,
+											  false, &newval, &newextra))
 						return 0;
 				}
 				else if (source == PGC_S_DEFAULT)
@@ -6247,6 +6391,295 @@ flatten_set_variable_args(const char *name, List *args)
 	return buf.data;
 }
 
+/*
+ * Writes updated configuration parameter values into
+ * postgresql.auto.conf.temp file. It traverses the list of parameters
+ * and quote the string values before writing them to temporaray file.
+ */
+static void
+write_auto_conf_file(int fd, const char *filename, ConfigVariable **head_p)
+{
+	ConfigVariable *item;
+	StringInfoData buf;
+
+	initStringInfo(&buf);
+	appendStringInfoString(&buf, "# Do not edit this file manually! \n");
+	appendStringInfoString(&buf, "# It will be overwritten by ALTER SYSTEM command. \n");
+
+	/*
+	 * write the file header message before contents, so that if there is no
+	 * item it can contain message
+	 */
+	if (write(fd, buf.data, buf.len) < 0)
+		ereport(ERROR,
+				(errmsg("failed to write to \"%s\" file", filename)));
+	resetStringInfo(&buf);
+
+	/*
+	 * traverse the list of parameters, quote the string parameter and write
+	 * it to file. Once all parameters are written fsync the file.
+	 */
+
+	for (item = *head_p; item != NULL; item = item->next)
+	{
+		char	   *escaped;
+
+		appendStringInfoString(&buf, item->name);
+		appendStringInfoString(&buf, " = ");
+
+		appendStringInfoString(&buf, "\'");
+		escaped = escape_single_quotes_ascii(item->value);
+		appendStringInfoString(&buf, escaped);
+		free(escaped);
+		appendStringInfoString(&buf, "\'");
+
+		appendStringInfoString(&buf, "\n");
+
+		if (write(fd, buf.data, buf.len) < 0)
+			ereport(ERROR,
+					(errmsg("failed to write to \"%s\" file", filename)));
+		resetStringInfo(&buf);
+	}
+
+	if (pg_fsync(fd) != 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not fsync file \"%s\": %m", filename)));
+
+	pfree(buf.data);
+}
+
+
+/*
+ * This function takes list of all configuration parameters in
+ * postgresql.auto.conf and parameter to be updated as input arguments and
+ * replace the updated configuration parameter value in a list. If the
+ * parameter to be updated is new then it is appended to the list of
+ * parameters.
+ */
+static void
+replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
+						  char *config_file,
+						  char *name, char *value)
+{
+	ConfigVariable *item,
+			   *prev = NULL;
+
+	if (*head_p != NULL)
+	{
+		for (item = *head_p; item != NULL; item = item->next)
+		{
+			if (strcmp(item->name, name) == 0)
+			{
+				pfree(item->value);
+				if (value != NULL)
+					/* update the parameter value */
+					item->value = pstrdup(value);
+				else
+				{
+					/* delete the configuration parameter from list */
+					if (*head_p == item)
+						*head_p = item->next;
+					else
+						prev->next = item->next;
+
+					if (*tail_p == item)
+						*tail_p = prev;
+
+					pfree(item->name);
+					pfree(item->filename);
+					pfree(item);
+				}
+				return;
+			}
+			prev = item;
+		}
+	}
+
+	if (value == NULL)
+		return;
+
+	item = palloc(sizeof *item);
+	item->name = pstrdup(name);
+	item->value = pstrdup(value);
+	item->filename = pstrdup(config_file);
+	item->next = NULL;
+
+	if (*head_p == NULL)
+	{
+		item->sourceline = 1;
+		*head_p = item;
+	}
+	else
+	{
+		item->sourceline = (*tail_p)->sourceline + 1;
+		(*tail_p)->next = item;
+	}
+
+	*tail_p = item;
+
+	return;
+}
+
+
+/*
+ * Persist the configuration parameter value.
+ *
+ * This function takes all previous configuration parameters
+ * set by ALTER SYSTEM command and the currently set ones
+ * and write them all to the automatic configuration file.
+ *
+ * The configuration parameters are written to a temporary
+ * file then renamed to the final name. The template for the
+ * temporary file is postgresql.auto.conf.temp.
+ *
+ * An LWLock is used to serialize writing to the same file.
+ *
+ * In case of an error, we leave the original automatic
+ * configuration file (postgresql.auto.conf) intact.
+ * A stale temporary file may be left behind in case we crash.
+ * Such files are removed on the next server restart.
+ */
+void
+AlterSystemSetConfigFile(AlterSystemStmt * altersysstmt)
+{
+	char	   *name;
+	char	   *value;
+	int			Tmpfd = -1;
+	FILE	   *infile;
+	struct config_generic *record;
+	ConfigVariable *head = NULL;
+	ConfigVariable *tail = NULL;
+	char		AutoConfFileName[MAXPGPATH];
+	char		AutoConfTmpFileName[MAXPGPATH];
+	struct stat st;
+	void	   *newextra = NULL;
+
+	if (!superuser())
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 (errmsg("must be superuser to execute ALTER SYSTEM command"))));
+
+	/*
+	 * Validate the name and arguments [value1, value2 ... ].
+	 */
+	name = altersysstmt->setstmt->name;
+
+	switch (altersysstmt->setstmt->kind)
+	{
+		case VAR_SET_VALUE:
+			value = ExtractSetVariableArgs(altersysstmt->setstmt);
+			break;
+
+		case VAR_SET_DEFAULT:
+			value = NULL;
+			break;
+		default:
+			elog(ERROR, "unrecognized alter system stmt type: %d",
+				 altersysstmt->setstmt->kind);
+			break;
+	}
+
+	record = find_option(name, false, LOG);
+	if (record == NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("unrecognized configuration parameter \"%s\"", name)));
+
+	if ((record->context == PGC_INTERNAL) ||
+		(record->flags & GUC_DISALLOW_IN_FILE))
+		ereport(ERROR,
+				(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+				 errmsg("parameter \"%s\" cannot be changed",
+						name)));
+
+	if (!validate_conf_option(record, name, value, ERROR,
+							  true, NULL, &newextra))
+		ereport(ERROR,
+				(errmsg("invalid value for parameter \"%s\": \"%s\"", name, value)));
+
+
+	/*
+	 * Use data directory as reference path for postgresql.auto.conf and it's
+	 * corresponding temp file
+	 */
+	join_path_components(AutoConfFileName, data_directory, PG_AUTOCONF_FILENAME);
+	canonicalize_path(AutoConfFileName);
+	snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s.%s",
+			 AutoConfFileName,
+			 "temp");
+
+	/*
+	 * one backend is allowed to operate on postgresql.auto.conf file, to
+	 * ensure that we need to update the contents of the file with
+	 * AutoFileLock. To ensure crash safety, first the contents are written to
+	 * temporary file and then rename it to postgresql.auto.conf
+	 */
+
+	LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);
+
+	Tmpfd = open(AutoConfTmpFileName, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
+	if (Tmpfd < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("failed to open auto conf temp file \"%s\": %m ",
+						AutoConfTmpFileName)));
+
+	PG_TRY();
+	{
+		if (stat(AutoConfFileName, &st) == 0)
+		{
+			/* open postgresql.auto.conf file */
+			infile = AllocateFile(AutoConfFileName, "r");
+			if (infile == NULL)
+				ereport(ERROR,
+						(errmsg("failed to open auto conf file \"%s\": %m ",
+								AutoConfFileName)));
+
+			/* Parse the postgresql.auto.conf file */
+			ParseConfigFp(infile, AutoConfFileName, 0, LOG, &head, &tail);
+
+			FreeFile(infile);
+		}
+
+		/*
+		 * replace with new value if the configuration parameter already
+		 * exists OR add it as a new cofiguration parameter in the file.
+		 */
+		replace_auto_config_value(&head, &tail, AutoConfFileName, name, value);
+
+		/* Write and sync the New contents to postgresql.auto.conf.temp file */
+		write_auto_conf_file(Tmpfd, AutoConfTmpFileName, &head);
+
+		close(Tmpfd);
+		Tmpfd = -1;
+
+		/*
+		 * As the rename is atomic operation, if any problem occurs after this
+		 * at max it can loose the parameters set by last ALTER SYSTEM
+		 * command.
+		 */
+		if (rename(AutoConfTmpFileName, AutoConfFileName) < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not rename file \"%s\" to \"%s\" : %m",
+							AutoConfTmpFileName, AutoConfFileName)));
+	}
+	PG_CATCH();
+	{
+		if (Tmpfd >= 0)
+			close(Tmpfd);
+
+		unlink(AutoConfTmpFileName);
+		FreeConfigVariables(head);
+		PG_RE_THROW();
+	}
+	PG_END_TRY();
+
+	FreeConfigVariables(head);
+	LWLockRelease(AutoFileLock);
+	return;
+}
 
 /*
  * SET command
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index f66f530..5bb463c 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1182,6 +1182,8 @@ setup_config(void)
 	char		repltok[MAXPGPATH];
 	char		path[MAXPGPATH];
 	const char *default_timezone;
+	char	   *autoconflines[3];
+	char		tempautobuf[256];
 
 	fputs(_("creating configuration files ... "), stdout);
 	fflush(stdout);
@@ -1269,6 +1271,24 @@ setup_config(void)
 	writefile(path, conflines);
 	chmod(path, S_IRUSR | S_IWUSR);
 
+	/*
+	 * create the automatic configuration file to store the configuration
+	 * parameters set by ALTER SYSTEM command. The parameters present in this
+	 * file will override the value of parameters that exists before parse of
+	 * this file.
+	 */
+
+	strcpy(tempautobuf, "# Do not edit this file manually! \n");
+	autoconflines[0] = pg_strdup(tempautobuf);
+	strcpy(tempautobuf, "# It will be overwritten by the ALTER SYSTEM command. \n");
+	autoconflines[1] = pg_strdup(tempautobuf);
+	autoconflines[2] = NULL;
+
+	sprintf(path, "%s/%s", pg_data, PG_AUTOCONF_FILENAME);
+
+	writefile(path, autoconflines);
+	chmod(path, S_IRUSR | S_IWUSR);
+
 	free(conflines);
 
 
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 78368c6..c808ccc 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -362,6 +362,7 @@ typedef enum NodeTag
 	T_CreateEventTrigStmt,
 	T_AlterEventTrigStmt,
 	T_RefreshMatViewStmt,
+	T_AlterSystemStmt,
 
 	/*
 	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 51fef68..496a852 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2435,6 +2435,16 @@ typedef struct DropdbStmt
 } DropdbStmt;
 
 /* ----------------------
+ *		Alter System Statement
+ * ----------------------
+ */
+typedef struct AlterSystemStmt
+{
+	NodeTag		type;
+	VariableSetStmt *setstmt;	/* SET subcommand */
+}	AlterSystemStmt;
+
+/* ----------------------
  *		Cluster Statement (support pbrown's cluster index implementation)
  * ----------------------
  */
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index 2e6aad1..9d116630 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -292,3 +292,10 @@
 /* #define HEAPDEBUGALL */
 /* #define ACLDEBUG */
 /* #define RTDEBUG */
+
+/*
+ * Automatic configuration file name for ALTER SYSTEM.
+ * This file will be used to store values of configuration parameters
+ * set by ALTER SYSTEM command
+ */
+#define PG_AUTOCONF_FILENAME		"postgresql.auto.conf"
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 39415a3..6677d53 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -80,6 +80,7 @@ typedef enum LWLockId
 	OldSerXidLock,
 	SyncRepLock,
 	BackgroundWorkerLock,
+	AutoFileLock,
 	/* Individual lock IDs end here */
 	FirstBufMappingLock,
 	FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS,
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 99211c1..8dc870a 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -326,6 +326,7 @@ extern bool parse_real(const char *value, double *result);
 extern int set_config_option(const char *name, const char *value,
 				  GucContext context, GucSource source,
 				  GucAction action, bool changeVal, int elevel);
+extern void AlterSystemSetConfigFile(AlterSystemStmt * setstmt);
 extern char *GetConfigOptionByName(const char *name, const char **varname);
 extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);
 extern int	GetNumConfigOptions(void);
