I understand that you could pass collection of Sobjects to Queueable apex classes but not to future methods where we’re restricted to only primitive collections. The reason it’s not done for future methods is that the objects could potentially change from the time it’s passed to the time when the future method executes.
Question – Will this hypothesis not hold true for Queueable apex and even batch apex for that matter since record value/criteria could change from when it’s executed by the start method to when it’s processed by the execute method. The exception to this would be if you take the sf org down for maintenance when the async jobs are run, in which case, this shouldn’t be an issue for all the async methods but not sure if this realistic – Is this correct understanding or am I missing something that’s not obvious in the developer guide.
Your logic is slightly flawed. All async code can run in to stale data. The difference between Batchable, Queueable, and Future methods is how they’re designed to behave. Batchable calls were designed to allow for heavy asynchronous processing. But, it was the only asynchronous code at one point, and it was too “heavy” in terms of resource usage, and had a lot of baggage associated with it. It required a long time to process and was often used only to handle callouts or things that were slightly longer than a normal transaction could handle.
So, next came future methods. Unlike Batchable methods, they were lighter on resources and perfect for doing that job that Batchable was doing before, but much more efficiently. Unfortunately, it was too efficient. You didn’t know when the job was done (no Job ID), and it only had a limited amount of space to store data (the reason why it only accepted primitives and collections thereof).
In response to feedback, a third version of asynchronous code was designed: Queueable. It was lighter than Batchable, but it gave you a Job ID and let you store complex data patterns. The lesser resources it used compared to batchable also meant higher limits. Queueable was meant to be a hybrid between the limited future methods and the resource-hungry Batchable interface.
So, to get back to your question: you should always avoid passing in entire SObjects, especially if they may change between serialization and execution. If you need heavy processing, you probably want Batchable, while if you want normal-sized transactions with increased limits, you probably want Queueable. Of course, you can still use future methods if you don’t need to monitor the results of the execution, and they’ll continue to work for the foreseeable future.