you want to use queues where you need to decouple processing of messages. In your simple (and common) example, you are writing to a local file and sending messages to a remote machine via TCP.
Sending logs via TCP is a process that can block. If there is a network problem or a server problem, the sender pauses delivery of logs. If there is not a queue for that action, then this will mean that you will also not write logs to the local files (including such useful information as logs saying that the remote system is down ;-) )
so in this case, you do want an action queue, so that the TCP connection can block without blocking writes to /var/log/messages.
A couple other things to think about here.
queues can be placed on actions or rulesets, if you are sending to multiple places (or want to failover from one to another), you want to group them in a ruleset and put the queue on the ruleset.
you REALLY want to use the new action() syntax if you are putting a queue on an action, the old syntax ($foo lines before the action) is FAR too easy to misunderstand what's happening
you can still lose messages in transit with TCP, when rsyslog gives the message to the OS on the sending machine, if that OS accepts it (i.e. doesn't say "the queue is full, wait"), rsyslog on the sender is forced to assume that it's going to be delivered. But if there is an outage (network or receiving server), rsyslog will never know that the message has been lost. The RELP protocol is designed to handle this case and resend messages if there are network/receiver issues.
as far as queues go, a 'direct queue' is 'no queue', it's the normal thing that happens when you have multiple actions
so a traditional
is an example of 'direct queues' They are the fastest way to process messages.
disk queues save every message to disk before processing and are EXTREMELY slow (something on the order of 1000x slowdown), but will survive a system crash
memory queues store the logs in ram (linkedlist of fixedarray differ in how they allocate ram and a bit of speed)
Disk Assisted queues are memory queues that will overflow to disk files rather than blocking further processing (draining the queues does not happen in order, the disk portion is drained in parallel with processing logs from the memory queue). This is a good choice to handle long outages, just be aware that after the outage, you will start getting current logs quickly, but older logs will arrive at a slower rate.
It is possible to overdo it with queues. When you have a memory queue, thread A needs to lock the queue to add the messages to the queue, then thread B needs to lock the queue to retrieve the messages from the queue to process them. If you have a lightweight output (i.e. writing to a file) you spend far more CPU locking and unlocking the queue than you would just writing the messages out.