Be aware that there are limits on future methods that you must consider when setting up such processing.
Note that there are limits on the number of future methods that can be invoked, as per the documentation:
Maximum number of methods with the future annotation allowed per Apex invocation: 50 (synchronous), 0 in batch and future contexts; 1 in queueable context
Recall that (standard SObject) triggers are invoked with up to 200 records at a time and if you have more than 200 records being inserted/updated/deleted/undeleted/etc. in a given DML operation then your trigger is invoked multiple times with different subsets (or "chunks") of the SObjects.
So, if each call to your trigger initiates a single future method then you can handle a maximum of 50 chunks of 200 records (which is 10000 records) which happens to be the maximum number of records you can update in a single session anyway. However, if your trigger is initiated from an async context you either cannot use a future at all (and since you cannot perform a callout in a trigger you cannot perform your callout) or you can support just one chunk of 200 records; any more and a governor limit uncatchable exception will be thrown, ruining your day.
Thus the pattern of using a future from a trigger to perform a callout is essentially broken since it will fail in various key scenarios. Sure, you can work around these by making sure you don't perform DML in async contexts, but you can pretty much guarantee that someone will have a need to do this on your org at some point in the future and then the sh*t will hit the fan.
You are therefore better to either consider using a Queueable or to use platform events to take the processing outside the current transaction. Both have their downsides:
- Until Transaction Finalizers GA you cannot reliably recover from a critical error (e.g. governor limit issue or uncaught exception) raised during queueable processing since you have no way to access the queueable's state. Additionally, you can only start a single queueable from the context of async processing.
- There can be edge cases where Platform Events are not delivered (even to a trigger-based event consumer). (I have never seen this scenario myself, but other community members have.)
The latter is captured in the documentation:
In rare cases, the event message might not be persisted in the distributed system during the initial or subsequent attempts. This means that the events aren’t delivered to subscribers, and they aren’t recoverable.
As noted, the main problem with queueables is that you are stuck if you have a need to initiate one per trigger chunk, you have more than 200 SObjects being operated on and you are already in an async context.
This basically means that the most flexible and robust solution is to use platform events and keep your fingers crossed you don't get hit by the nasty edge case mentioned above. TBH, it strikes me that if this edge case is gonna hit your org it's probably going to mess up more than just the delivery of platform events.