The reason why PostgreSQL decides to perform a Sequential Scan of the listings
table is because there is just one row. In that case, reading the whole table takes less time than using an index.
If you just add more data to the listings
table, PostgreSQL changes plans, because then, reading the whole table is no longer the cheapest alternative:
dbfiddle here
PostgreSQL (and most other databases) has a Query Planner that chooses an execution plan based on a cost-estimate of all available alternatives. The cost-estimate is based on the amount and statistical distribution of data within the different columns of the different tables, and takes into consideration the availability of indexes, but will choose to use them only if it is the cheapest alternative (or you force it to use them via settings).
With a query as simple as thisthe one in this example, just joining two tables using an equality JOIN condition, you shouldn't need to outsmart PostgreSQL query planner. Let the planner plan. It will nearly always choose the best plan.
You may need to play some tricks when JOINs are much more complicated (many: many more tables, conditions which aren't necessarily just equalities, function calls, correlations between tables that the planner doesn't take into account, etc. ... and the planner ends up making bad estimates oncost-estimates, and the number of rows to be retrieved in every case)estimated cheapest plan is not really the cheapest.