title: Redis: Why is Lua scripting going to replace transactions?
body: <p>The documentation for transactions says:</p>
  
  <blockquote>
    <p>"we may deprecate and finally remove transactions" and "everything you
    can do with a Redis transaction, you can also do with a script"</p>
  </blockquote>
  
  <p><a href="http://redis.io/topics/transactions" rel="noreferrer">http://redis.io/topics/transactions</a></p>
  
  <p>But does it? I see a problem with this.</p>
  
  <p>Within a transaction you can WATCH multiple variables, read those variables, and based on the unique state of those variables you can make a completely different set of writes before calling EXEC. If anything interferes with the state of those variables in the intervening time, EXEC will not perform the transaction. (Which allows you to retry it. This is a perfect transaction system.)</p>
  
  <p>An EVAL script will not let you do that. According to the documentation on this page:</p>
  
  <blockquote>
    <p>"Scripts as pure functions...The script always evaluates the same
    Redis write commands with the same arguments given the same input data
    set. Operations performed by the script cannot depend on any hidden
    (non explicit) information or state that may change as script
    execution proceeds or between different executions of the script, nor
    can it depend on any external input from I/O devices."</p>
  </blockquote>
  
  <p><a href="http://redis.io/commands/eval" rel="noreferrer">http://redis.io/commands/eval</a></p>
  
  <p>The problem I see with EVAL is that you cannot GET the state of those variables inside of the script and make a unique set of writes based on the state of those variables. Again: "The script always evaluates the same Redis write commands with the same arguments given the same input data set." So the resulting writes are already determined (cached from the first run) and the EVAL script doesn't care what the GET values are inside of the script. The only thing you can do is perform GET for those variables before calling EVAL and then pass those variables to the EVAL script, but here's the problem: now you have an atomicity problem between calling GET and calling EVAL.</p>
  
  <p>In other words, all the variables that you would have done a WATCH for a transaction, in the case of EVAL you instead need to GET those variables and then pass them to the EVAL script. Since the atomic nature of the script isn't guaranteed until the script actually starts, and you need to GET those variables before calling EVAL to start the script, that leaves an opening where the state of those variables could change between the GET and passing them to EVAL. Therefore, the guarantee of atomicity that you have with WATCH you do not have with EVAL for a very important set of use cases.</p>
  
  <p>So why is there talk about deprecating transactions when that would cause important Redis functionality to be lost? Or is there actually a way to do this with EVAL scripts that I do not understand yet? Or are there features planned that can solve this for EVAL? (Hypothetical example: if they made WATCH work with EVAL the same way that WATCH works with EXEC, that might work.)</p>
  
  <p>Is there a solution to this? Or am I to understand that Redis may not be completely transaction safe in the long term?</p>