begin with <literal>pg_</literal>, it is best to
avoid such names to ensure that you won't suffer a conflict if some
future version defines a system table named the same as your
table. (With the default search path, an unqualified reference to
your table name would then be resolved as the system table instead.)
System tables will continue to follow the convention of having
names beginning with <literal>pg_</literal>, so that they will not
conflict with unqualified user-table names so long as users avoid
the <literal>pg_</literal> prefix.
</para>
</sect2>
<sect2 id="ddl-schemas-patterns">
<title>Usage Patterns</title>
<para>
Schemas can be used to organize your data in many ways.
A <firstterm>secure schema usage pattern</firstterm> prevents untrusted
users from changing the behavior of other users' queries. When a database
does not use a secure schema usage pattern, users wishing to securely
query that database would take protective action at the beginning of each
session. Specifically, they would begin each session by
setting <varname>search_path</varname> to the empty string or otherwise
removing schemas that are writable by non-superusers
from <varname>search_path</varname>. There are a few usage patterns
easily supported by the default configuration:
<itemizedlist>
<listitem>
<para>
Constrain ordinary users to user-private schemas.
To implement this pattern, first ensure that no schemas have
public <literal>CREATE</literal> privileges. Then, for every user
needing to create non-temporary objects, create a schema with the
same name as that user, for example
<literal>CREATE SCHEMA alice AUTHORIZATION alice</literal>.
(Recall that the default search path starts
with <literal>$user</literal>, which resolves to the user
name. Therefore, if each user has a separate schema, they access
their own schemas by default.) This pattern is a secure schema
usage pattern unless an untrusted user is the database owner or
has been granted <literal>ADMIN OPTION</literal> on a relevant role,
in which case no secure schema usage pattern exists.
</para>
<!-- A database owner can attack the database's users via "CREATE SCHEMA
trojan; ALTER DATABASE $mydb SET search_path = trojan, public;". -->
<para>
In <productname>PostgreSQL</productname> 15 and later, the default
configuration supports this usage pattern. In prior versions, or
when using a database that has been upgraded from a prior version,
you will need to remove the public <literal>CREATE</literal>
privilege from the <literal>public</literal> schema (issue
<literal>REVOKE CREATE ON SCHEMA public FROM PUBLIC</literal>).
Then consider auditing the <literal>public</literal> schema for
objects named like objects in schema <literal>pg_catalog</literal>.
</para>
<!-- "DROP SCHEMA public" is inferior to this REVOKE, because pg_dump
doesn't preserve that DROP. -->
</listitem>
<listitem>
<para>
Remove the public schema from the default search path, by modifying
<link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>
or by issuing <literal>ALTER ROLE ALL SET search_path =
"$user"</literal>. Then, grant privileges to create in the public
schema. Only qualified names will choose public schema objects. While
qualified table references are fine, calls to functions in the public
schema <link linkend="typeconv-func">will be unsafe or
unreliable</link>. If you create functions or extensions in the public
schema, use the first pattern instead. Otherwise, like the first
pattern, this is secure unless an untrusted user is the database owner
or has been granted <literal>ADMIN