JOIN tables and return count even if it is 0
LEFT JOIN is the key, like ypercube commented.

And you probably don't need the self-join - assuming settings.customer_id is unique not null.

If your predicate is selective (more than a few rows without alarms), I suggest to count in a LATERAL subquery:

SELECT s.customer_id, s.current::jsonb-&gt;'alarms' AS alarms
     , coalesce(r.reg_ct, 0) AS reg_ct
FROM   settings s
LEFT   JOIN LATERAL (
   SELECT count(*) AS reg_ct
   FROM   registration
   WHERE  customer_id = s.customer_id
   AND    date = '2018-10-10'
   ) r ON true
WHERE  s.current::jsonb-&gt;'alarms' IS NOT NULL;


Else, a plain subquery should be faster:

SELECT s.customer_id, s.current::jsonb-&gt;'alarms' AS alarms
     , coalesce(r.reg_ct, 0) AS reg_ct
FROM   settings s
LEFT   JOIN (
   SELECT customer_id, count(*) AS reg_ct
   FROM   registration
   WHERE  date = '2018-10-10'
   GROUP  BY 1
   ) r USING (customer_id)
WHERE  s.current::jsonb-&gt;'alarms' IS NOT NULL;


Either way, it's typically faster and less error prone to aggregate before the join.
Related:


Understanding multiple table join with aggregation
What is the difference between LATERAL and a subquery in PostgreSQL?