Recursion on deletion trigger that calls a function
Add the following at the beginning of your function:

IF pg_trigger_depth() &gt; 1 THEN
   RETURN OLD;
END IF;


Then recursion will be cut short after the first iteration.

To avoid the error that you get when the same row is deleted twice in the same statement, explicitly exclude it:

DELETE ...
WHERE ...
  AND OLD.ctid &lt;&gt; ctid