Postgres cascades truncates to unrelated tables I've created a number of tables in my public schema.

Occasionally, I need to run a seeder to refresh the users table when I perform tests. To do this, I'm executing TRUNCATE TABLE users RESTART IDENTITY CASCADE.

However, I do not want any other tables but those related to the users table to be affected. The only foreign key referencing the users table is on the teams table which references users through owner_id. The teams table truncates as expected.

What isn't expected, is that the attributes table is also truncated by TRUNCATE TABLE users RESTART IDENTITY CASCADE.

The attributes table has one foreign key on the accounts table which references the users table. However, on the attributes table, ALL account_id values are NULL so there is no actual reference back on any of the records to a specific record in the accounts table. In fact, at the time of executing the truncate query, the entire accounts table is already empty.

How then is TRUNCATE TABLE users RESTART IDENTITY CASCADE causing my attributes table to be truncated based on NULL foreign keys?
I think TRUNCATE ... CASCADE doesn't do any reference checking on foreign key values, that would defeat the purpose. The mere presense of referential integrity constraints connecting attributes to users via accounts causes all three (and possibly more) tables to be truncated (which you would have noticed if accounts weren't empty).