Los índices únicos en Postgres se basan en valores que son iguales , pero NULL nunca es igual a nada, incluidos otros NULL. Por lo tanto, cualquier fila con un valor NULL delete_at es distinta de cualquier otra fila posible, por lo que puede insertar cualquier número de ellas.
Una forma de evitar esto es crear índices parciales , aplicando diferentes reglas a las filas con y sin NULL:
CREATE UNIQUE INDEX ... ON subscriptions
(user_id, class_type_id) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX ... ON subscriptions
(user_id, class_type_id, deleted_at) WHERE deleted_at IS NOT NULL;