A primary key or unique constraint on a partitioned table must include all partition key columns, because each partition only enforces uniqueness locally
The key must include the partition key column, so PRIMARY KEY (id, created_at) works. PostgreSQL enforces uniqueness with a separate index on each partition. There is no global index across all partitions. So PostgreSQL can only guarantee uniqueness if the partition key is part of the constraint.
"Partitioned tables cannot have primary keys" is wrong. Partitioned tables can have primary keys. They just have this restriction.
Read more