Índices exclusivos no Postgres são baseados em valores iguais , mas NULL nunca é igual a nada, incluindo outros NULLs. Portanto, qualquer linha com um valor NULL delete_at é diferente de qualquer outra linha possível - portanto, você pode inserir qualquer número delas.
Uma maneira de contornar isso é criar índices parciais , aplicando regras diferentes a linhas com e sem NULLs:
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;