This is a fantastic explanation.
We have started to do something similar but your LUA rewrites is a lot more effective. I wasn't even aware that you could do something like that.
We have also done similar things to test our new platform, using nginx and cookies, by sending part of the traffic to the new platform to be beta tested. Didn't need to use lua though.
http://qzaidi.github.com/2012/03/11/nginx-ab/
We've done this before, but by adding an additional load-balancer that forwards requests to a different port (e.g. 81 instead of 80) depending on the subdomain that was accessed. The request is processed by nginx, which has separate server blocks and associated upstreams for processing requests that come in over the configured ports. The only application logic that was necessary to accommodate the changes was a check to determine if the user should be part of the beta, and redirect them to the appropriate subodmain if necessary.
While it's not as clean as having the check done in nginx itself via Lua script + Redis, it's relatively low friction. That said, the Lua script embedded in the nginx config is very slick, and I had been contemplating writing something similar using the nginx memcache module. Nice work.
Yes that works too as I mentioned in the first couple of paragraphs of the post.
However having a beta.mixlr.com domain a) introduces a lot of friction and seriously reduces the ease with which you can test features b) may alter the perception or expectations of a visitor, making testing less valid.
We've got a lot of users and we want to make the roll-out process completely transparent and inclusive.
Good write up for a sensible solution to a problem which should effect lots of sites.
Personally, I would probably take the approach of settings a cookie per user. This would be very suitable when beta testing is enabled/decided by users, rather than a subset being chosen A/B style based on a value in the database. This would have the advantage that nginx would not have to make any database requests; just check a cookie on the request, likely speeding up the speed at which nginx handles requests. However, it would require some changes to the application (versus [small] changes to the database which the slug approach) to set the cookie etc.
Cheers. Yeah a cookie approach would be suitable for a lot of uses, including A/B testing. It's easy in Nginx/Lua:
local is_some_cookie_set = nginx.var.cookie_SomeCookie ~= nil;
Then you don't need Redis at all. For us though, we want to separate users by the URL and then a check at an application level variable, so I think this is the right approach still.
Couldn't you use a cookie and map, rather than URLs? Sounds like users could end up on different rails back ends unintentionally based on what URL they use, with your method...