My database background is with Oracle, so I was surprised to discover that Postgres includes schema changes in transactions - if you begin one, create a table and then rollb
Two sessions concurrently running "CREATE TABLE" is a little racy:
http://postgresql.1045698.n5.nabble.com/Errors-on-CREATE-TABLE-IF-NOT-EXISTS-td5659080.html
CREATE TABLE does a preliminary check to see whether a name conflict exists. If so, it either errors out (normally) or exits with a notice (in the IF NOT EXISTS case). But there's a race condition: a conflicting transaction can create the table after we make that check and before we create it ourselves.
Both the linked thread initiator and I hit this in automated testing environments, so it's not much more than an annoyance there. (I doubt it would effect your schema migrations, but it can be seen as a limit on ddl changes)
perl -MDBI -E 'fork; fork; $d=DBI->connect("dbi:Pg:dbname=$ENV{USER}");' \
$d->do("CREATE TABLE a (b int)")'
DBD::Pg::db do failed: ERROR:
duplicate key value violates unique constraint "pg_type_typname_nsp_index"
DETAIL: Key (typname, typnamespace)=(a, 2200) already exists. at -e line 1.