There might be more than one reason for this:
From the
documentation:
Important: When you are billed for instance hours, you will not see any instance classes in your billing line items. Instead, you will see the appropriate multiple of instance hours. For example, if you use an F4 instance for one hour, you do not see "F4" listed, but you will see billing for four instance hours at the F1 rate.
So in your case with F4_1G, which costs 0.30$ per hour, rather than 0.05$ per hour of a B1 instance, this is factor 6. The billings always show instance hours as B1, so 72 hours F4_1G translates to 432 hours B1. The same applies to the billing dashboard.
However, there can indeed be more instances with your setup, than the 3 you want, hence the "min-idle-instances":
Auto scaling modules use dynamic instances - but if you specify a number, N, of minimum idle instances, the first N instances will be resident, and additional dynamic instances will be created as necessary.
For example, if your cron job handler has an error and exponentially adds tasks into the queue. Or if tasks run much longer than expected, so additional instances are needed to handle the overlapping tasks. With your setup it is possible that you end up with more than three F4_1G instances during peeks, but never will fall below three. If I understand idle instances correctly, that means that at least three instances will be running that do nothing. If your cron-job starts, a fourth instance would be started, so there will always be three idle instances, plus the instances that are processing the cron-jobs.
You can limit this, either in auto-scaling (e.g.
max_idle_instances), or kind of ultimately, you can set a daily budget. I recommend to check again the dashboard from your screenshot, just to be certain what the reason is for your instance hours. There is the "Summary" button on top. Toggle it to "Instances" diagram and switch the period to 1 day, for example, just to see if there were any peeks with more than 3 instances.
As far as I understand, you have no user-facing features in your app (or this module), but only cron-jobs? Do you expect to have always same load for your app or module? Maybe it doesn't matter if your cron-jobs have to wait a few additional seconds until a new instance is spawned (just in case). If the answers are all yes, you could consider basic-scaling with max-instances set to 3. If you set the idle_timeout to something longer than your 5 minute cron-job schedule (e.g. 10m), the setup could work fine for your use-case.