</listitem>
      </varlistentry>
 
+     <varlistentry id="libpq-connect-servicefile" xreflabel="servicefile">
+      <term><literal>servicefile</literal></term>
+      <listitem>
+       <para>
+        This option specifies the name of the per-user connection service file
+        (see <xref linkend="libpq-pgservice"/>).
+        Defaults to <filename>~/.pg_service.conf</filename>, or
+        <filename>%APPDATA%\postgresql\.pg_service.conf</filename> on
+        Microsoft Windows.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="libpq-connect-target-session-attrs" xreflabel="target_session_attrs">
       <term><literal>target_session_attrs</literal></term>
       <listitem>
       <indexterm>
        <primary><envar>PGSERVICEFILE</envar></primary>
       </indexterm>
-      <envar>PGSERVICEFILE</envar> specifies the name of the per-user
-      connection service file
-      (see <xref linkend="libpq-pgservice"/>).
-      Defaults to <filename>~/.pg_service.conf</filename>, or
-      <filename>%APPDATA%\postgresql\.pg_service.conf</filename> on
-      Microsoft Windows.
+      <envar>PGSERVICEFILE</envar> behaves the same as the
+      <xref linkend="libpq-connect-servicefile"/> connection parameter.
      </para>
     </listitem>
 
    On Microsoft Windows, it is named
    <filename>%APPDATA%\postgresql\.pg_service.conf</filename> (where
    <filename>%APPDATA%</filename> refers to the Application Data subdirectory
-   in the user's profile).  A different file name can be specified by
+   in the user's profile).  A different file name can be specified using the
+   <literal>servicefile</literal> key word in a libpq connection string or by
    setting the environment variable <envar>PGSERVICEFILE</envar>.
    The system-wide file is named <filename>pg_service.conf</filename>.
    By default it is sought in the <filename>etc</filename> directory
 
                "Database-Service", "", 20,
        offsetof(struct pg_conn, pgservice)},
 
+       {"servicefile", "PGSERVICEFILE", NULL, NULL,
+               "Database-Service-File", "", 64,
+       offsetof(struct pg_conn, pgservicefile)},
+
        {"user", "PGUSER", NULL, NULL,
                "Database-User", "", 20,
        offsetof(struct pg_conn, pguser)},
        free(conn->dbName);
        free(conn->replication);
        free(conn->pgservice);
+       free(conn->pgservicefile);
        free(conn->pguser);
        if (conn->pgpass)
        {
 parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
 {
        const char *service = conninfo_getval(options, "service");
+       const char *service_fname = conninfo_getval(options, "servicefile");
        char            serviceFile[MAXPGPATH];
        char       *env;
        bool            group_found = false;
                return 0;
 
        /*
-        * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
-        * exists).
+        * First, try the "servicefile" option in connection string.  Then, try
+        * the PGSERVICEFILE environment variable.  Finally, check
+        * ~/.pg_service.conf (if that exists).
         */
-       if ((env = getenv("PGSERVICEFILE")) != NULL)
+       if (service_fname != NULL)
+               strlcpy(serviceFile, service_fname, sizeof(serviceFile));
+       else if ((env = getenv("PGSERVICEFILE")) != NULL)
                strlcpy(serviceFile, env, sizeof(serviceFile));
        else
        {
                                if (strcmp(key, "service") == 0)
                                {
                                        libpq_append_error(errorMessage,
-                                                                          "nested service specifications not supported in service file \"%s\", line %d",
+                                                                          "nested \"service\" specifications not supported in service file \"%s\", line %d",
+                                                                          serviceFile,
+                                                                          linenr);
+                                       result = 3;
+                                       goto exit;
+                               }
+
+                               if (strcmp(key, "servicefile") == 0)
+                               {
+                                       libpq_append_error(errorMessage,
+                                                                          "nested \"servicefile\" specifications not supported in service file \"%s\", line %d",
                                                                           serviceFile,
                                                                           linenr);
                                        result = 3;
        }
 
 exit:
+
+       /*
+        * If a service has been successfully found, set the "servicefile" option
+        * if not already set.  This matters when we use a default service file or
+        * PGSERVICEFILE, where we want to be able track the value.
+        */
+       if (*group_found && result == 0)
+       {
+               for (i = 0; options[i].keyword; i++)
+               {
+                       if (strcmp(options[i].keyword, "servicefile") != 0)
+                               continue;
+
+                       /* If value is already set, nothing to do */
+                       if (options[i].val != NULL)
+                               break;
+
+                       options[i].val = strdup(serviceFile);
+                       if (options[i].val == NULL)
+                       {
+                               libpq_append_error(errorMessage, "out of memory");
+                               result = 3;
+                       }
+                       break;
+               }
+       }
+
        fclose(f);
 
        return result;
 
        char       *dbName;                     /* database name */
        char       *replication;        /* connect as the replication standby? */
        char       *pgservice;          /* Postgres service, if any */
+       char       *pgservicefile;      /* path to a service file containing
+                                                                * service(s) */
        char       *pguser;                     /* Postgres username and password, if any */
        char       *pgpass;
        char       *pgpassfile;         /* path to a file containing password(s) */
 
   or die "Could not copy $srvfile_valid to $srvfile_nested: $!";
 append_to_file($srvfile_nested, 'service=invalid_srv' . $newline);
 
+# Service file with nested "servicefile" defined.
+my $srvfile_nested_2 = "$td/pg_service_nested_2.conf";
+copy($srvfile_valid, $srvfile_nested_2)
+  or die "Could not copy $srvfile_valid to $srvfile_nested_2: $!";
+append_to_file($srvfile_nested_2,
+       'servicefile=' . $srvfile_default . $newline);
+
 # Set the fallback directory lookup of the service file to the temporary
 # directory of this test.  PGSYSCONFDIR is used if the service file
 # defined in PGSERVICEFILE cannot be found, or when a service file is
 
        $dummy_node->connect_fails(
                'service=my_srv',
-               'connection with nested service file',
+               'connection with "service" in nested service file',
+               expected_stderr =>
+                 qr/nested "service" specifications not supported in service file/);
+
+       local $ENV{PGSERVICEFILE} = $srvfile_nested_2;
+
+       $dummy_node->connect_fails(
+               'service=my_srv',
+               'connection with "servicefile" in nested service file',
                expected_stderr =>
-                 qr/nested service specifications not supported in service file/);
+                 qr/nested "servicefile" specifications not supported in service file/
+       );
+}
+
+# Properly escape backslashes in the path, to ensure the generation of
+# correct connection strings.
+my $srvfile_win_cared = $srvfile_valid;
+$srvfile_win_cared =~ s/\\/\\\\/g;
+
+# Checks that the "servicefile" option works as expected
+{
+       $dummy_node->connect_ok(
+               q{service=my_srv servicefile='} . $srvfile_win_cared . q{'},
+               'connection with valid servicefile in connection string',
+               sql => "SELECT 'connect3_1'",
+               expected_stdout => qr/connect3_1/);
+
+       # Encode slashes and backslash
+       my $encoded_srvfile = $srvfile_valid =~ s{([\\/])}{
+               $1 eq '/' ? '%2F' : '%5C'
+       }ger;
+
+       # Additionally encode a colon in servicefile path of Windows
+       $encoded_srvfile =~ s/:/%3A/g;
+
+       $dummy_node->connect_ok(
+               'postgresql:///?service=my_srv&servicefile=' . $encoded_srvfile,
+               'connection with valid servicefile in URI',
+               sql => "SELECT 'connect3_2'",
+               expected_stdout => qr/connect3_2/);
+
+       local $ENV{PGSERVICE} = 'my_srv';
+       $dummy_node->connect_ok(
+               q{servicefile='} . $srvfile_win_cared . q{'},
+               'connection with PGSERVICE and servicefile in connection string',
+               sql => "SELECT 'connect3_3'",
+               expected_stdout => qr/connect3_3/);
+
+       $dummy_node->connect_ok(
+               'postgresql://?servicefile=' . $encoded_srvfile,
+               'connection with PGSERVICE and servicefile in URI',
+               sql => "SELECT 'connect3_4'",
+               expected_stdout => qr/connect3_4/);
+}
+
+# Check that the "servicefile" option takes priority over the PGSERVICEFILE
+# environment variable.
+{
+       local $ENV{PGSERVICEFILE} = 'non-existent-file.conf';
+
+       $dummy_node->connect_fails(
+               'service=my_srv',
+               'connection with invalid PGSERVICEFILE',
+               expected_stderr =>
+                 qr/service file "non-existent-file\.conf" not found/);
+
+       $dummy_node->connect_ok(
+               q{service=my_srv servicefile='} . $srvfile_win_cared . q{'},
+               'connection with both servicefile and PGSERVICEFILE',
+               sql => "SELECT 'connect4_1'",
+               expected_stdout => qr/connect4_1/);
 }
 
 $node->teardown_node;