<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mixlr Tech</title>
    <description>Mixlr is an audio broadcasting company based in London. On Mixlr Tech, we'll be sharing some of what we learn about technology, coding and scalability.
</description>
    <link>http://tech.mixlr.com/</link>
    <atom:link href="http://tech.mixlr.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 14 Sep 2021 07:40:16 +0000</pubDate>
    <lastBuildDate>Tue, 14 Sep 2021 07:40:16 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
      <item>
        <title>5 development principles we strive for at Mixlr</title>
        <description>&lt;p&gt;&lt;a name=&quot;top&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;info_block&quot;&gt;&lt;strong&gt;We're hiring.&lt;/strong&gt; If you enjoy this post, you might enjoy being part of our team too. &lt;a href=&quot;/jobs&quot;&gt;Visit the Mixlr jobs homepage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we started Mixlr over five years ago, we’ve experimented with a lot of different approaches to development.&lt;/p&gt;

&lt;p&gt;Here are five principles that we’ve found particularly valuable over that time.&lt;/p&gt;

&lt;h4 id=&quot;release-early-and-often-even-if-its-not-perfect-yet&quot;&gt;Release early and often. (Even if it’s not perfect yet.)&lt;/h4&gt;

&lt;p&gt;This is the first rule of the &lt;a href=&quot;http://agilemanifesto.org/principles.html&quot;&gt;Agile manifesto&lt;/a&gt;, but arguably the most important - and even more so when you’ve got a small team, and a big user base.&lt;/p&gt;

&lt;p&gt;The Mixlr community has over 45,000 monthly active broadcasters and millions of monthly listeners.&lt;/p&gt;

&lt;p&gt;To keep everybody satisfied, we have little choice but to aim to release features and improvements frequently, despite our small team size.&lt;/p&gt;

&lt;p&gt;We start at the product design phase, defining clear user stories at the earliest possible opportunity, and then stick with them throughout the development cycle. This helps us to focus on improvements that our users really want, and avoid wasted development time.&lt;/p&gt;

&lt;p&gt;When it comes to release, we always favour pushing new code as early as possible.&lt;/p&gt;

&lt;p&gt;This doesn’t mean that allowing a user’s experience to regress is acceptable, of course. We make careful use of tools like Google Analytics, &lt;a href=&quot;http://www.mixpanel.com&quot;&gt;Mixpanel&lt;/a&gt;, Browserstack and &lt;a href=&quot;http://www.airbrake.io&quot;&gt;Airbrake&lt;/a&gt; to be sure that won’t happen.&lt;/p&gt;

&lt;p&gt;But with these safeguards in place, we can allow our community to benefit from new features quickly — even if they’re not quite pixel perfect yet.&lt;/p&gt;

&lt;p&gt;And with early release comes early dialog too, which helps us finetune and improve a feature more efficiently than we ever could in a closed QA environment.&lt;/p&gt;

&lt;h4 id=&quot;readability-counts&quot;&gt;Readability counts.&lt;/h4&gt;

&lt;p&gt;Once again, Mixlr’s ultra-low ratio of developers to active users makes this principle crucial for us.&lt;/p&gt;

&lt;p&gt;Code is nothing if it isn’t readable — and readable by others, not just the original developer.&lt;/p&gt;

&lt;p&gt;Once again, there’s no simple way to achieve this.&lt;/p&gt;

&lt;p&gt;Why write a nested ternary statement, when you can space that logic out onto half-a-dozen lines and make it pulse with clarity and simplicity?&lt;/p&gt;

&lt;p&gt;When writing Ruby, is that early return statement triggered by a &lt;a href=&quot;http://seejohncode.com/2012/07/31/ruby-gotcha-single-line-conditionals/&quot;&gt;dangling conditional&lt;/a&gt; worth sacrificing a clear, fully-indented code path that can be understood at a glance?&lt;/p&gt;

&lt;p&gt;Can that variable &lt;em&gt;really&lt;/em&gt; not be named a little more descriptively?&lt;/p&gt;

&lt;p&gt;These are questions we try to ask of every commit, because if we can create code that’s easy to read, then we’ve probably built something that’s easy to maintain too. And everybody, including our users, benefits from that in the long-run.&lt;/p&gt;

&lt;h4 id=&quot;keep-the-code-visible&quot;&gt;Keep the code visible.&lt;/h4&gt;

&lt;p&gt;As &lt;a href=&quot;http://www.exceptionnotfound.net/fundamental-laws-of-software-development/&quot;&gt;Linus’s Law states&lt;/a&gt;, enough eyeballs make all bugs shallow.&lt;/p&gt;

&lt;p&gt;We try to learn from this at Mixlr in a couple of ways.&lt;/p&gt;

&lt;p&gt;Firstly, by encouraging our team to review each other’s code on an adhoc basis. Once again, &lt;a href=&quot;http://konrad-reiche.com/2015/12/26/continuous-code-review-with-github-and-slack.html&quot;&gt;Slack is a great tool here&lt;/a&gt;, integrating closely with Github to make the code we commit visible to everybody within seconds.&lt;/p&gt;

&lt;p&gt;And secondly, by enabling more formal code reviews and &lt;a href=&quot;http://guide.agilealliance.org/guide/pairing.html&quot;&gt;pair programming&lt;/a&gt; opportunities whenever possible.&lt;/p&gt;

&lt;p&gt;Apart from directly increasing overall code quality, this also all has the advantage of exposing more of our backend infrastructure to our team, which is a great learning opportunity too.&lt;/p&gt;

&lt;h4 id=&quot;if-it-moves-test-it&quot;&gt;If it moves, test it.&lt;/h4&gt;

&lt;p&gt;Writing automated tests isn’t just about ensuring the code you’re writing right now is solid. It also tends to bring a number of other potential benefits to a project.&lt;/p&gt;

&lt;p&gt;For starters, it’s possible to move much, much faster when you’re confident that the changes you’re making have left other parts of an application unaffected. So our users benefit now, and then time and again later too.&lt;/p&gt;

&lt;p&gt;Unit testing also naturally tends to engender modular, easy-to-understand code — something which helps improve the long-term maintainability of a project in ways which are difficult to foresee.&lt;/p&gt;

&lt;p&gt;Our Ruby on Rails applications feature comprehensive test suites, and with &lt;a href=&quot;http://tech.mixlr.com/development/2016/02/09/five-ways-to-use-slack-jenkins.html&quot;&gt;the help of Jenkins and Slack&lt;/a&gt; we keep them at the heart of our day-to-day process.&lt;/p&gt;

&lt;h4 id=&quot;deployments-are-frictionless&quot;&gt;Deployments are frictionless.&lt;/h4&gt;

&lt;p&gt;If we’re going to release early and often, then we’d better make sure that our deploy process allows it.&lt;/p&gt;

&lt;p&gt;We use &lt;a href=&quot;http://capistranorb.com/&quot;&gt;Capistrano&lt;/a&gt; for all of our main projects, which gives us a common deployment interface that our entire development team is familiar with.&lt;/p&gt;

&lt;p&gt;During a recent upgrade to Capistrano 3, we also refactored and modularised all of our deploy hooks, making the system significantly easier to understand and modify.&lt;/p&gt;

&lt;p&gt;We use &lt;a href=&quot;https://github.com/mattbrictson/airbrussh&quot;&gt;Matt Brictson’s Airbrussh gem&lt;/a&gt; to prettify and improve the coherence of the Capistrano output.&lt;/p&gt;

&lt;p&gt;Our internal staging site provides us an ideal environment for testing and otherwise experimenting with the deploy process, and tight integration with Slack means that our team always knows who is deploying what to where.&lt;/p&gt;

&lt;p&gt;All of this means that our entire team is comfortable with deploying to production (often from their very first day with us), so we can fix bugs quicker and deploy new features more readily than we would otherwise be able to.&lt;/p&gt;

&lt;p&gt;Read more: &lt;a href=&quot;https://zachholman.com/posts/deploying-software&quot;&gt;How to deploy software&lt;/a&gt;&lt;/p&gt;

</description>
        <pubDate>Thu, 28 Apr 2016 12:00:00 +0000</pubDate>
        <link>http://tech.mixlr.com/development/2016/04/28/development-principles-mixlr.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/development/2016/04/28/development-principles-mixlr.html</guid>
        
        <category>development,</category>
        
        <category>testing,</category>
        
        <category>code</category>
        
        <category>quality,</category>
        
        <category>agile</category>
        
        
        <category>development</category>
        
      </item>
    
      <item>
        <title>Five ways to use Slack part two: How we made Campfire sounds work in Slack</title>
        <description>&lt;p&gt;In this post we show you how Mixlr pushes Slack beyond its boundaries; how we let the genie out of the bottle–into the office. Before Mixlr got addicted to Slack we used Campfire. One of the features that made Campfire, the real-time communication tool for team collaboration, indistinguishable is the feature to play sounds to everyone. From sounds like &lt;a href=&quot;https://emoji-cheat-sheet.campfirenow.com/sounds/dangerzone.mp3&quot;&gt;Danger Zone&lt;/a&gt; from Topgun, over George Takei’s &lt;a href=&quot;https://emoji-cheat-sheet.campfirenow.com/sounds/ohmy.mp3&quot;&gt;Oh My&lt;/a&gt;, to Ludacris’ &lt;a href=&quot;https://emoji-cheat-sheet.campfirenow.com/sounds/rollout.mp3&quot;&gt;Roll Out&lt;/a&gt;, there is a sound to emphasise every kind of situation; be it a colleague spilling coffee over your laptop or a successful rollout of a new feature.&lt;/p&gt;

&lt;p&gt;After Mixlr migrated to Slack we found ourselves becoming more and more productive with every new integration we added. The lack of sounds though, was a wound which would not heal. We take great pride in our office stereo as it not only enables us to listen to music, share new discoveries but also use our product in a communal way. With a Raspberry Pi available in the office, this screamed out for an &lt;strong&gt;office hack&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/slack-sounds.jpg&quot; alt=&quot;Mixlr's Raspberry Pi connceted to our mix deck&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;buy-it-plug-it-play-it&quot;&gt;Buy it, plug it, play it&lt;/h3&gt;

&lt;p&gt;The Raspberry Pi is a credit card–sized single-board computer developed with the intent to promote the teaching of basic computer science in schools and developing countries. It has gained popularity as a supplementing device especially due to its size and low amount of power demand hence making it ideal for interacting with the environment.&lt;/p&gt;

&lt;p&gt;The plan was to connect the Raspberry Pi to our speakers to play sounds from it. Our speakers are set up through a mix deck which means it would be just a matter of connecting the Raspberry Pi to it in order to make any output sounds available while maintaining our office music sounds.&lt;/p&gt;

&lt;p&gt;Slack allows you to define &lt;a href=&quot;https://api.slack.com/outgoing-webhooks&quot;&gt;outgoing webhooks&lt;/a&gt; or even &lt;a href=&quot;https://api.slack.com/slash-commands&quot;&gt;slash commands&lt;/a&gt;. For instance, you could define the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/sound [name]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that you need to tell Slack to which endpoint it should post the data as soon as someone enters the command. Maybe you can already guess how everything fits together.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/slack-sounds-diagram.png&quot; alt=&quot;A Slack command triggers the Slack webhook to post to our Raspberry Pi which then in turn plays a sound on our office speakers&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We let Slack post that message directly to our Raspberry Pi which then in turn would trigger the sounds using &lt;a href=&quot;http://www.mpg123.com/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mpg123&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SoundsDir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.mp3&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mpg123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;:speaker: *%s* is playing _%s_&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sendChatResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For that we built a web server &lt;strong&gt;Huck 9000&lt;/strong&gt; (name inspired by our patron saint Mick Hucknall) using Go which parses the different HTTP messages and translates them into Linux commands to be executed on the Raspberry Pi.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/slack-sounds-trombone.png&quot; alt=&quot;Mixlr HQ Sounds reporting back to Slack which sound is played&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It is such a simple setup but if you think about it opens up so many possibilities in terms of extensibility: setting up a timer to play coffee sounds when the brew is done, connecting it to our office TV and show a random GIF on every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/giphy&lt;/code&gt; or even detecting the song which is currently played on the speakers and posting it back to Slack. We already use it to gather everyone for our daily standup:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/slack-sounds-standup.png&quot; alt=&quot;Mixlr HQ Sounds summoning everyone for daily standup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Feel free to take a look at the implementation as we have &lt;a href=&quot;https://github.com/mixlr/huck-9000&quot;&gt;open sourced the code&lt;/a&gt;. Clearly, these are just simple and fun things but they enable you to think in a creative way about your workplace and even though it does not directly improve our product it heavily improves our day to day happiness and you never know when one of these hacks lead to another innovative idea as well.&lt;/p&gt;
</description>
        <pubDate>Mon, 04 Apr 2016 13:00:00 +0000</pubDate>
        <link>http://tech.mixlr.com/development/2016/04/04/five-ways-to_use-slack-sounds.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/development/2016/04/04/five-ways-to_use-slack-sounds.html</guid>
        
        <category>software</category>
        
        <category>engineering,</category>
        
        <category>startup,</category>
        
        <category>slack,</category>
        
        <category>code</category>
        
        <category>quality,</category>
        
        <category>tests</category>
        
        
        <category>development</category>
        
      </item>
    
      <item>
        <title>5 ways we work as a team at Mixlr</title>
        <description>&lt;p&gt;&lt;a name=&quot;top&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;info_block&quot;&gt;&lt;strong&gt;We're hiring.&lt;/strong&gt; If you enjoy reading this post, you'll find Mixlr is a great team to be a part of. &lt;a href=&quot;/jobs&quot;&gt;Visit the Mixlr jobs homepage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At Mixlr, we’ve racked up more than five years of experience working as a team to create our service.&lt;/p&gt;

&lt;p&gt;Along the way, we’ve also accumulated a few methods that help us work together effectively as a team on a day-to-day basis. Here are some of our favourites.&lt;/p&gt;

&lt;h4 id=&quot;daily-standup&quot;&gt;Daily standup&lt;/h4&gt;

&lt;p&gt;A standup is one of the &lt;a href=&quot;http://martinfowler.com/articles/itsNotJustStandingUp.html&quot;&gt;most commonly known&lt;/a&gt; agile methodologies. Everybody in the team comes together for a few minutes, to recap what they worked on yesterday, and what they’re planning to work on today.&lt;/p&gt;

&lt;p&gt;We find it’s a great start to the day for a few reasons.&lt;/p&gt;

&lt;p&gt;Firstly, it ensures that everybody’s first act of the day involves communicating with the whole group, which we find helps get the day off to a positive start.&lt;/p&gt;

&lt;p&gt;Secondly, it’s an easy way for everybody to keep track of what others are working on. If a team member is unable to proceed with their task-in-hand for some reason, then the standup helps unblocking to happen naturally.&lt;/p&gt;

&lt;p&gt;After some previous attempts, we’ve settled for now on a simple format that works well for us. For reasons too archaic to pin down, a generous and not remotely ironic dose of &lt;a href=&quot;https://www.youtube.com/watch?v=8qc1B2PbM2g&quot;&gt;Mick Hucknall&lt;/a&gt; is involved.&lt;/p&gt;

&lt;h4 id=&quot;in-office-sound-effects&quot;&gt;In-office sound effects&lt;/h4&gt;

&lt;p&gt;We use &lt;a href=&quot;https://slack.com/&quot;&gt;Slack&lt;/a&gt; for group chat at Mixlr, ever since migrating away from the erstwhile number one Campfire.&lt;/p&gt;

&lt;p&gt;Slack has proven more useful, and infinitely more addictive, but there’s one thing we sorely missed - Campfire’s &lt;a href=&quot;https://www.quora.com/What-are-all-the-sounds-you-can-play-in-campfire-campfirenow-com&quot;&gt;sound effects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There’s nothing like being able to drop a creative sad trombone into conversation to help make one’s point. So we decided to act.&lt;/p&gt;

&lt;p&gt;Our team member Konrad — with the help of a &lt;a href=&quot;https://www.raspberrypi.org/&quot;&gt;Raspberry Pi&lt;/a&gt;, the Go programming language and &lt;a href=&quot;https://api.slack.com/slash-commands&quot;&gt;Slack’s command API&lt;/a&gt; — built an ingenious custom sound effects system that allows any of our team to use Slack to trigger a library of custom sound effects over the office sound system.&lt;/p&gt;

&lt;p&gt;And it works… amazingly well.&lt;/p&gt;

&lt;p&gt;We now have not only the Campfire sound library, but an ever-growing cumulation of custom sounds too.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/soundsystem1.jpg&quot; alt=&quot;The Mixlr office sound system&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;1-to-1s&quot;&gt;1-to-1s&lt;/h4&gt;

&lt;p&gt;Every fortnight, each member of the Mixlr team gets out of the office and spends a scheduled hour one-to-one with their first-contact manager.&lt;/p&gt;

&lt;p&gt;The subject of the meeting varies, and is ultimately up to the team member: it’s their time to discuss on-going projects, vent about any frustrations they may have, and ask questions about anything and everything.&lt;/p&gt;

&lt;p&gt;We’re still in the early days of our adoption of regular 1-to-1s, but we’re already seeing some profoundly positive benefits: new lines of communication being opened up, and interesting and valuable discussions which quite likely would otherwise never have occurred.&lt;/p&gt;

&lt;p&gt;There’s no doubt that 1-to-1s will be an important part of our process going forward.&lt;/p&gt;

&lt;h4 id=&quot;real-time-customer-milestones&quot;&gt;Real-time customer milestones&lt;/h4&gt;

&lt;p&gt;It’s a nice feeling when the work you’ve done has led to a new customer signing up, or a user sending us an positive email.&lt;/p&gt;

&lt;p&gt;We try to make the most of this by having key customer milestones posted automatically into Slack.&lt;/p&gt;

&lt;p&gt;When a customer signs up or renews their subscription, or creates a new event — everybody can see that it’s happened, instantly. (And the same goes for new support cases, @replies on Twitter, cancellations, and a whole lot more besides).&lt;/p&gt;

&lt;p&gt;We also post automated daily updates of our key company KPIs for our team each morning, which helps to improve overall transparency too.&lt;/p&gt;

&lt;p&gt;Real-time milestones have helped our team to feel more connected with our product and users.&lt;/p&gt;

&lt;h4 id=&quot;friday-beers--techproduct-talks&quot;&gt;Friday beers + tech/product talks&lt;/h4&gt;

&lt;p&gt;On Fridays, work finishes at 5pm and we break for beers and tech talks.&lt;/p&gt;

&lt;p&gt;Often, individual team members informally present what they’ve been working on that week, which is another great opportunity for everybody to keep in the loop of upcoming product changes and improvements.&lt;/p&gt;

&lt;p&gt;Sometimes, there’s a more generic tech subject that somebody is interested in demonstrating. Occasionally, we end up in the pub instead. Either way, it’s a great tradition that’s fun, and helps to ensure our team winds down from the week effectively (and perhaps a little bit drunk).&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Related: &lt;a href=&quot;http://tech.mixlr.com/development/2016/02/02/10-open-source-technologies-at-mixlr.html&quot;&gt;10 open source technologies we use to build Mixlr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/beers.png&quot; alt=&quot;Mixlr beers&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Thu, 31 Mar 2016 12:00:00 +0000</pubDate>
        <link>http://tech.mixlr.com/team/2016/03/31/ways-we-work-as-a-team-at-mixlr.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/team/2016/03/31/ways-we-work-as-a-team-at-mixlr.html</guid>
        
        <category>process,</category>
        
        <category>agile,</category>
        
        <category>tools,</category>
        
        <category>team</category>
        
        
        <category>team</category>
        
      </item>
    
      <item>
        <title>How we get the perfect shuffle for your playlist in the Mixlr app</title>
        <description>&lt;p class=&quot;info_block&quot;&gt;&lt;strong&gt;We're hiring!&lt;/strong&gt; Are you a developer who wants to work on interesting technical challenges with a small, passionate team here in London? For more information, visit the &lt;a href=&quot;/jobs&quot;&gt;Mixlr jobs homepage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Playlist shuffle was a feature added to the Mixlr desktop app in 2015 after popular demand from users.
Shuffling can be approached in different ways from a technical perspective, but is hard to get “right” from a user perspective.
Youtube solves the problem by randomly sorting the playlist, which may be fine for a youtube listener playlist, but a Mixlr broadcaster probably wouldn’t want their lists being randomly rearranged.
If you can think back to the way Winamp performed with shuffled tracks in a playlist, you may have had an experience where one of your &lt;a href=&quot;https://thetfp.com/tfp/tilted-technology/60783-how-does-winamps-shuffle-work.html&quot;&gt;favourite tracks never seemed to play&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/shuffle.png&quot; alt=&quot;Shuffle control in the Mixlr desktop app&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At Mixlr, we wanted to nail the user experience for shuffling, using a high quality (in terms of bias) algorithm/technique.
The shuffle feature was well received, and we would like to share our method for both learning and re-use; please read on for the juicy details.&lt;/p&gt;

&lt;h4 id=&quot;getting-the-shuffle-right&quot;&gt;Getting the shuffle right&lt;/h4&gt;

&lt;p&gt;Writing an algorithm to perform a shuffle, at first thought, sounds quite easy.
A quick solution might involve selecting a random number from &lt;span&gt;\(1\)&lt;/span&gt; to &lt;span&gt;\(N\)&lt;/span&gt; (where &lt;span&gt;\(N\)&lt;/span&gt; is the number of tracks you have loaded in your playlist) and choosing that track to play. 
This process could simply be repeated to select the next track. Sounds OK in principle, but it’s not actually a good solution for several reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The shuffle is biased, in the worst case it could result in one track being played more than others, whilst another track never gets played.&lt;/li&gt;
  &lt;li&gt;Each track has a fixed (and biased!) probability of playback. That means there’s a possibility that one track could be selected multiple times in a row.&lt;/li&gt;
  &lt;li&gt;There is no control over the probability - i.e. to manipulate the selection likelihood of a particular track&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are algorithms available for shuffling that solve the biasing issue (e.g. the &lt;a href=&quot;https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle&quot;&gt;Fisher-Yates-Knuth shuffle&lt;/a&gt;).
However, we want more control over the shuffle to subjectively increase the quality of track playback order from a human perspective.&lt;/p&gt;

&lt;h4 id=&quot;the-shuffle-experience&quot;&gt;The shuffle experience&lt;/h4&gt;

&lt;p&gt;Shuffling in a way that “feels right” is a challenge in and of itself; having a intuitive user experience would have to inform algorithm design.
There were certain requirements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Randomness - a proper random selection rather than a playlist sort. Because it feels more authentically random if you hear a track repeated in a short period.&lt;/li&gt;
  &lt;li&gt;Controlling repetition - yes we want randomness, but not to the point of annoyance. It should be much less likely (but still possible) to hear the same track repeated in a short period.&lt;/li&gt;
  &lt;li&gt;All tracks matter - if we have &lt;span&gt;\(N\)&lt;/span&gt; tracks, and &lt;span&gt;\(N - 1\)&lt;/span&gt; different tracks have played, it should be much more likely to select the track &lt;span&gt;\(T_j\)&lt;/span&gt; which hasn’t played, rather than the previously selected track &lt;span&gt;\(T_{\mu}\)&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These requirements mean that this problem is different to shuffling a pack of cards.
We need to assign and compute the probability of each track playing and make a random selection based on all probabilities (i.e. a type of &lt;a href=&quot;http://stackoverflow.com/questions/177271/roulette-selection-in-genetic-algorithms&quot;&gt;stochastic roulette wheel selection&lt;/a&gt;).&lt;/p&gt;

&lt;h4 id=&quot;shuffling-using-random-sampling&quot;&gt;Shuffling using random sampling&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Sampling_(statistics)&quot;&gt;Random sampling&lt;/a&gt; is a method that is straightforward to understand and implement.
The general idea behind random sampling to select &lt;em&gt;individuals&lt;/em&gt; of a &lt;em&gt;population&lt;/em&gt; using random numbers; in our case we have a population of tracks.
Our approach differs from simple random sampling as we assign a &lt;em&gt;propensity (weighted probability)&lt;/em&gt; to each track which is modified when a track is played (set to zero) but slowly increases over time.
This form of selection requires us to record the sum of the propensity of all tracks &lt;span&gt;\(P_{total}\)&lt;/span&gt; and multiply it by a random number &lt;span&gt;\(r_1\)&lt;/span&gt; in the range &lt;span&gt;\([0.0, 1.0]\)&lt;/span&gt; to generate a &lt;em&gt;“target propensity”&lt;/em&gt; &lt;span&gt;\(P_{target}\)&lt;/span&gt;.
Note that we recommend using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Mersenne_Twister&quot;&gt;Mersenne Twister&lt;/a&gt; psuedo-random number generator, it has a period that far exceeds the requirements of this application yet is computationally inexpensive.&lt;/p&gt;

&lt;center&gt;&lt;span&gt;$$P_{total} = \sum_{i=1}^NP_i(T)$$&lt;/span&gt;&lt;/center&gt;

&lt;center&gt;&lt;span&gt;$$T_{\mu} = \min\left\{\mu|\sum_{j=1}^{j=\mu} a_j(x) &amp;gt; r_1P_{total}(x)\right\}$$&lt;/span&gt;&lt;/center&gt;

&lt;p&gt;Using &lt;span&gt;\(P_{target}\)&lt;/span&gt; we can select an individual track by assessing its “position” in the list of tracks propensities (by summing propensities until we hit the target).&lt;/p&gt;

&lt;p&gt;Here are the major stages to our approach:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Assign every track a propensity - in our case start the integer &lt;span&gt;\(N\)&lt;/span&gt; (where &lt;span&gt;\(N\)&lt;span&gt; is total the number of tracks).&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;Pick a random number &lt;span&gt;\(r_1\)&lt;/span&gt; in the range &lt;span&gt;\([0.0, 1.0]\)&lt;/span&gt; and multiply it by the total track propensities &lt;span&gt;\(P_{total}\)&lt;/span&gt; to get a “target propensity” &lt;span&gt;\(P_{target}\)&lt;/span&gt;.&lt;/li&gt;
  &lt;li&gt;Iterate over tracks and sum propensities until &lt;span&gt;\(P_{target}\)&lt;/span&gt; is reached - select the last track &lt;span&gt;\(T_{\mu}\)&lt;/span&gt; we iterated over to play.&lt;/li&gt;
  &lt;li&gt;Reduce the propensity of the last track &lt;span&gt;\(T_{\mu}\)&lt;/span&gt; we played - in our case we set it to &lt;span&gt;\(0\)&lt;/span&gt;.&lt;/li&gt;
  &lt;li&gt;Update the propensities of any other tracks that are less than &lt;span&gt;\(N\)&lt;/span&gt; (i.e. ones that have been recently played) - in our case we add &lt;span&gt;\(1\)&lt;/span&gt;.&lt;/li&gt;
  &lt;li&gt;Recalculate the total propensity &lt;span&gt;\(P_{total}\)&lt;/span&gt; of all tracks.&lt;/li&gt;
  &lt;li&gt;GOTO 2.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This method satisfies the requirements of our shuffle experience: it provides good quality randomness, limits repetition and increases the likelihood of a previously unheard track getting airtime.&lt;/p&gt;

</description>
        <pubDate>Fri, 11 Mar 2016 13:54:00 +0000</pubDate>
        <link>http://tech.mixlr.com/development/2016/03/11/playlist-shuffing.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/development/2016/03/11/playlist-shuffing.html</guid>
        
        <category>Monte</category>
        
        <category>Carlo,</category>
        
        <category>shuffle,</category>
        
        <category>shuffling,</category>
        
        <category>playlist,</category>
        
        <category>random</category>
        
        
        <category>development</category>
        
      </item>
    
      <item>
        <title>Five ways to use Slack part one: Jenkins CI</title>
        <description>&lt;p&gt;Slack found its way into many startups where it is not only celebrated as a convenient communication tool. At Mixlr we try to utilize our tool chains not only to increase productivity but to make our whole work environment more fun. In order to really grasp the potential of Slack you need to experience and try it out. In this series we want to show you how we at Mixlr use Slack beyond its pure chat functionality.&lt;/p&gt;

&lt;h4 id=&quot;what-is-slack&quot;&gt;What is Slack?&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;http://slack.com/&quot;&gt;Slack&lt;/a&gt; is a team messaging app for synchronous and asynchronous communication across different devices. Above all it is a tool which might seem simple at first glance but becomes powerful by adding integrations that knit tightly with your workflow.&lt;/p&gt;

&lt;p&gt;Rather than just a collection of chat rooms it can be better described as a communication hub. Different channels can represent different teams, different topics or a very specific type of information that should stream into that particular channel.&lt;/p&gt;

&lt;h4 id=&quot;what-is-jenkins-ci&quot;&gt;What is Jenkins CI?&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://jenkins-ci.org/&quot;&gt;Jenkins&lt;/a&gt; is an open source continuous integration tool written in Java and arguably the most widely used one as well. Jenkins supports distributed agents and a build process. What you can do with Jenkins depends on your imagination due to its freedom of configuration and plethora of available plugins. A job, respectively project, can represent different things in Jenkins: compilation of a particular piece of software, running your unit tests or deploying to your production environment as soon as certain conditions are met. Jenkins offers a rich API to report back any details which makes it possible to utilize these information.&lt;/p&gt;

&lt;h4 id=&quot;jenkins-and-slack-at-mixlr&quot;&gt;Jenkins and Slack at Mixlr&lt;/h4&gt;

&lt;p&gt;Writing tests with every new piece of function added to our back or front end is an essential part of the workflow at Mixlr. Our tests already cover the core functionality of our app. It is crucial that changes do not break any existing behavior as it could pottentially affect thousand of users. While it is nice to have these tests executing in a job in Jenkins CI and getting notified via email if somethings breaks it is not exactly as transparent or live as it could be.&lt;/p&gt;

&lt;p&gt;We build a small addition to the existing Jenkins integration to give us more detail as soon as something is pushed to the repository or changed. No matter if master branch or feature branch, we are quite happy and used to the following view in our Slack #dev channel:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/jenkins-passing.png&quot; alt=&quot;All tests are passing and Jenkins post that into Slack&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Although admittedly we all slip and fall sometimes. If that happens we would see something like that:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/jenkins-failing.png&quot; alt=&quot;Tests got broken and Jenkins post that into Slack mentioning the culprit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unexpected failure can always occur. Though it is crucial that when something fails it will definitely not get pushed back but tackled immediately by our team. We enjoy contributing to a code base for which all of us take ownership. Increasing visibility also helps us to keep in mind that everyone at Mixlr is acting in concert and from time to time also a good laugh in the office when you just did not see that push breaking someone else’s tests.&lt;/p&gt;
</description>
        <pubDate>Tue, 09 Feb 2016 15:00:00 +0000</pubDate>
        <link>http://tech.mixlr.com/development/2016/02/09/five-ways-to-use-slack-jenkins.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/development/2016/02/09/five-ways-to-use-slack-jenkins.html</guid>
        
        <category>software</category>
        
        <category>engineering,</category>
        
        <category>startup,</category>
        
        <category>slack,</category>
        
        <category>code</category>
        
        <category>quality,</category>
        
        <category>tests</category>
        
        
        <category>development</category>
        
      </item>
    
      <item>
        <title>We're hiring</title>
        <description>&lt;p&gt;We’re currently hiring for a number of roles, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Backend Developer&lt;/li&gt;
  &lt;li&gt;Frontend Developer&lt;/li&gt;
  &lt;li&gt;Community Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these roles are full-time, permanent and based at Mixlr HQ at &lt;a href=&quot;https://www.instagram.com/netilhouse/&quot;&gt;Netil House&lt;/a&gt;, nestled in the heart of East London. You’ll be joining our small, friendly and focused team and building the world’s biggest audio broadcasting service.&lt;/p&gt;

&lt;p&gt;For more information and a full list of current opportunities, &lt;a href=&quot;/jobs&quot;&gt;visit our jobs page&lt;/a&gt;. And we’d love to hear from you too - drop us a line via &lt;a href=&quot;http://mixlr.com/help/contact&quot;&gt;http://mixlr.com/help/contact&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/netil360.png&quot; alt=&quot;Netil rooftop&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 04 Feb 2016 14:00:00 +0000</pubDate>
        <link>http://tech.mixlr.com/jobs/2016/02/04/were-hiring.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/jobs/2016/02/04/were-hiring.html</guid>
        
        <category>jobs</category>
        
        
        <category>jobs</category>
        
      </item>
    
      <item>
        <title>10 open source technologies we use at Mixlr</title>
        <description>&lt;p&gt;&lt;a name=&quot;top&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;info_block&quot;&gt;&lt;strong&gt;We're hiring.&lt;/strong&gt; If you're a backend developer who is passionate about building rock-solid, high-availability systems using open source technology, you may find Mixlr to be a great team to join. &lt;a href=&quot;/jobs&quot;&gt;Visit the Mixlr jobs homepage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We rely on a host of amazing open source technologies to build the Mixlr platform. This post offers an overview of some of our favourite examples, and why they play such a big part in building our service.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#postgresql&quot;&gt;PostgreSQL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#redis&quot;&gt;Redis&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nginx&quot;&gt;Nginx&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#haproxy&quot;&gt;Haproxy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lua&quot;&gt;Lua&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#puppet&quot;&gt;Puppet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ruby&quot;&gt;Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rails&quot;&gt;Ruby on Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nodejs&quot;&gt;NodeJS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#jenkins&quot;&gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;postgresql&quot;&gt;PostgreSQL&lt;a name=&quot;postgresql&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;PostgreSQL has been our main database since we migrated away from MySQL in early 2015.&lt;/p&gt;

&lt;p&gt;Our experiences with Postgres so far have been very positive, especially bearing in mind that after five years of running a fast-growing startup we have a &lt;em&gt;lot&lt;/em&gt; of data to deal with.&lt;/p&gt;

&lt;p&gt;Even when working with tables containing hundreds of millions of rows, Postgres allows us to continue carrying out many routine administration tasks - such as adding or removing columns or building indexes - without locking tables and forcing our service offline. This is an area that MySQL in particular is notoriously deficient in, and had previously caused our development team numerous pulsating headaches.&lt;/p&gt;

&lt;p&gt;Postgres has other advantages too: helpful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXPLAIN&lt;/code&gt; output, advanced constraints and a host of custom cell types for modelling data like IP addresses, JSON and complex container types, to name but a few.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.postgresql.org/&quot;&gt;PostgreSQL homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.quora.com/What-are-pros-and-cons-of-PostgreSQL-and-MySQL&quot;&gt;What are the pros and cons of PostgreSQL and MySQL?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;redis&quot;&gt;Redis&lt;a name=&quot;redis&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;This fast, stable and elegant example of open source software powers many things at Mixlr. From acting as a short-term caching layer a la &lt;a href=&quot;http://memcached.org/&quot;&gt;Memcached&lt;/a&gt;, storing sessions for our web application, or acting as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern&quot;&gt;pubsub server&lt;/a&gt; delivering real-time messages to tens of thousands of client applications - it just works.&lt;/p&gt;

&lt;p&gt;If there’s one thing not to love about Redis, it’s just a little bit &lt;em&gt;too&lt;/em&gt; versatile. As with Maslow’s hammer, there is a tendency for everything to start to look like a candidate for storing or processing in Redis - even when there are better options for data persistence readily available. For this reason, we are careful to never put data into Redis that we wouldn’t be too unhappy to lose without warning.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/antirez/redis&quot;&gt;Redis source code&lt;/a&gt; is regularly hailed as an example of concise, well-written C.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://redis.io/&quot;&gt;Redis homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.pivotal.io/pivotal/case-studies/using-redis-at-pinterest-for-billions-of-relationships&quot;&gt;Using Redis at Pinterest for billions of relationships&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;nginx&quot;&gt;Nginx&lt;a name=&quot;nginx&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Nginx has quickly usurped Apache to become the most popular front-end web server in the world. It is also responsible for serving almost every HTTP request received by the Mixlr website, API and backend services.&lt;/p&gt;

&lt;p&gt;Its event-driven design makes serving static files, assets and images incredibly pain-free.&lt;/p&gt;

&lt;p&gt;And its modular configuration system allow us to easily optimise, secure and otherwise polish every part of our website and API.&lt;/p&gt;

&lt;p&gt;Let’s not forget its integration with the Lua scripting language, discussed more &lt;a href=&quot;#lua&quot;&gt;below&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.nginx.com/&quot;&gt;Nginx homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.quora.com/Why-is-nginx-so-efficient&quot;&gt;Why is Nginx so efficient?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;haproxy&quot;&gt;Haproxy&lt;a name=&quot;haproxy&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Sticking with HTTP processing tools, The Haproxy loadbalancer is another essential part of our infrastructure.&lt;/p&gt;

&lt;p&gt;Although Nginx provides some duplicate functionality, Haproxy’s low-level and fine-grained configurability allow us to make the most of a relatively small pool of backend Ruby on Rails servers. This avoids most unnecessary backlogs forming when proxying requests, meaning our users are much more likely to be served the content they want as quickly as possible.&lt;/p&gt;

&lt;p&gt;And of course a smaller pool of backend servers saves us a bunch of money and time too.&lt;/p&gt;

&lt;p&gt;Much like Redis, it’s also another great example of a highly efficient, elegant tool that just works.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.haproxy.org/&quot;&gt;Haproxy homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://highscalability.com/blog/2014/7/21/stackoverflow-update-560m-pageviews-a-month-25-servers-and-i.html/&quot;&gt;Stackoverflow update: 560M page views a month, it’s all about performance&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;lua&quot;&gt;Lua&lt;a name=&quot;lua&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Lua is a compact, powerful (and characterful) scripting language. It’s so small that it’s become a de facto choice for embedded systems, making appearances in many &lt;a href=&quot;https://en.wikipedia.org/wiki/Category:Lua-scripted_video_games&quot;&gt;games&lt;/a&gt; and industrial software packages.&lt;/p&gt;

&lt;p&gt;For Mixlr, its allure is in its ability to be embedded in the Nginx web server. Lua code can be triggered at numerous points of the Nginx request/response cycle, giving us arbitrary programmatic access to the entire Nginx environment (not to mention external HTTP services, Redis, and more).&lt;/p&gt;

&lt;p&gt;The possibilities here are clearly many - others have even implemented &lt;a href=&quot;https://openresty.org/&quot;&gt;entire web application frameworks&lt;/a&gt; using Nginx and Lua.&lt;/p&gt;

&lt;p&gt;We don’t go quite that far, but we do make use of Lua to further fine-tune our HTTP services, implement &lt;a href=&quot;http://tech.mixlr.com/development/2016/01/25/how-to-handle-csrf-token-when-page-caching.html&quot;&gt;advanced page-caching strategies&lt;/a&gt;, and a lot more besides.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.lua.org/about.html&quot;&gt;Lua homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/openresty/lua-nginx-module&quot;&gt;Nginx/Lua module&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.cloudflare.com/pushing-nginx-to-its-limit-with-lua/&quot;&gt;Pushing Nginx to its limits with Lua&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;puppet&quot;&gt;Puppet&lt;a name=&quot;puppet&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Mixlr would likely not exist in its current form today if it wasn’t for Puppet. We use the configuration management system to define each and every one of our backend servers: what software and updates are installed, the location and content of configuration files, cron jobs, iptables rules, and lots more besides.&lt;/p&gt;

&lt;p&gt;The value of Puppet comes in the time we save each time we deploy a new server. Instead of a day of manual and error-prone effort, spinning up a new box typically takes just minutes - and is repeated precisely, each and every time.&lt;/p&gt;

&lt;p&gt;Unlike alternative Chef, Puppet has a declarative approach to configuration - a limitation we’ve found has actually been a positive influence in keeping our Puppet manifests simple and easy to understand.&lt;/p&gt;

&lt;p&gt;Puppet is also at the heart of our autoscaling systems, allowing our service to respond quickly and automatically to unexpected spikes in traffic.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://puppetlabs.com/&quot;&gt;Puppet homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.quora.com/Configuration-Management/Which-should-I-choose-Chef-Puppet-Ansible-SaltStack-Docker-or-something-else&quot;&gt;Configuration management software - which should I choose?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;ruby&quot;&gt;Ruby&lt;a name=&quot;ruby&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Hailing from Japan, the popularity of the Ruby programming language has exploded over the last decade, mostly powered by its adoption by web developers across the world.&lt;/p&gt;

&lt;p&gt;Ruby deserves being appreciated as a great open source project in its own right, however. The brainchild of Yukihiro Matsumoto - aka Matz - it is slightly idiosyncratic in style, infinitely flexible and - in the right hands - a profoundly powerful tool that’s also relatively easy to learn.&lt;/p&gt;

&lt;p&gt;One of Ruby’s most distinguishing features is its aptness for creating &lt;a href=&quot;http://martinfowler.com/books/dsl.html&quot;&gt;domain-specific languages&lt;/a&gt; - small, specialised and efficient interfaces to sub-parts of a particular software system or application. At Mixlr we’ve used Ruby to build a DSL which defines our internal API, for example.&lt;/p&gt;

&lt;p&gt;Ruby code also glues most of the Mixlr backend infrastructure together, its transparent interoperability with kernel and shell level functionality making it a great fit.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ruby-lang.org/&quot;&gt;Ruby homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://learnrubythehardway.org/book/&quot;&gt;Learn Ruby the hard way&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;ruby-on-rails&quot;&gt;Ruby on Rails&lt;a name=&quot;rails&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;The world’s most opinionated web framework powers Mixlr’s website, API and internal tools.&lt;/p&gt;

&lt;p&gt;Rails turns building web applications into an incredibly productive pursuit, helped by its preference for convention over configuration - meaning the days of endless XML configuration files are thankfully (largely) behind us.&lt;/p&gt;

&lt;p&gt;And then there’s the small matter of an active and highly passionate community, and a &lt;a href=&quot;https://rubygems.org/&quot;&gt;huge library of third party libraries&lt;/a&gt;, aka gems, to make development easier.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Ruby on Rails homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.codecademy.com/learn/learn-rails&quot;&gt;Learn Rails at Codecadamy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;nodejs&quot;&gt;NodeJS&lt;a name=&quot;nodejs&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;NodeJS burst into life in 2009, when Ryan Dahl got &lt;a href=&quot;https://www.youtube.com/watch?v=ztspvPYybIY&quot;&gt;tired of trying to do non-blocking I/O in Ruby&lt;/a&gt; and decided to write his own JavaScript-based, C++-powered event-driven network programming framework.&lt;/p&gt;

&lt;p&gt;Perfect for building low-latency, high-performance systems, we use NodeJS in two main applications: powering our real-time messaging services (which provide chat and other social features on Mixlr, amongst many other jobs) and also in a suite of custom audio streaming servers.&lt;/p&gt;

&lt;p&gt;The power and flexibility of NodeJS means it will likely play a big role in the future of our infrastructure.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://nodejs.org/&quot;&gt;NodeJS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://techblog.netflix.com/2014/11/nodejs-in-flames.html&quot;&gt;NodeJS in flames at Netflix&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;jenkins&quot;&gt;Jenkins&lt;a name=&quot;jenkins&quot;&gt;&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;One of the most recent additions to this collection, Jenkins is an “&lt;em&gt;open source automation server&lt;/em&gt;” - also known as a &lt;a href=&quot;https://www.thoughtworks.com/continuous-integration&quot;&gt;continuous integration tool&lt;/a&gt;. Like many others, we use Jenkins to automate the running of unit and functional tests on our main Rails applications.&lt;/p&gt;

&lt;p&gt;Jenkins makes it possible to automatically trigger a full test run every time one of our development team pushes a new change to GitHub. This simple but poweful behaviour, combined with clever integration with Slack, has profoundly increased the usefulness of the tests by making it impossible for anybody to not know they are failing.&lt;/p&gt;

&lt;p&gt;Watch this space for more information about the impact Jenkins has been having on our daily workflow.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://jenkins-ci.org/&quot;&gt;Jenkins homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.quora.com/What-is-Jenkins-When-and-why-is-it-used&quot;&gt;What is Jenkins? When and why is it used?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#top&quot;&gt;Back to top&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;next&quot;&gt;Next…?&lt;/h4&gt;

&lt;p&gt;We’re hiring backend developers, and you soon be adding to this list yourself. Interested? &lt;a href=&quot;/jobs&quot;&gt;Visit the Mixlr jobs homepage&lt;/a&gt; to find out more.&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Feb 2016 12:00:00 +0000</pubDate>
        <link>http://tech.mixlr.com/development/2016/02/02/10-open-source-technologies-at-mixlr.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/development/2016/02/02/10-open-source-technologies-at-mixlr.html</guid>
        
        <category>backend</category>
        
        <category>technology</category>
        
        <category>lists</category>
        
        
        <category>development</category>
        
      </item>
    
      <item>
        <title>How to make CSRF protection work with page caching</title>
        <description>&lt;p class=&quot;info_block&quot;&gt;&lt;strong&gt;We're hiring!&lt;/strong&gt; Are you a web developer who wants to work on interesting technical challenges with a small, passionate team here in London? We'd love to chat more: drop us a line via &lt;a href=&quot;mailto:jobs@mixlr.com&quot;&gt;jobs@mixlr.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here at Mixlr we are accustomed to building our service to work well in high-traffic scenarios. We also place a high premium on maintaining our users’ security and safety. But what happens when these two essential goals conflict with each other?&lt;/p&gt;

&lt;p&gt;One example of this is maintaining &lt;a href=&quot;http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf&quot;&gt;CSRF protection&lt;/a&gt; whilst also benefitting from &lt;a href=&quot;http://guides.rubyonrails.org/caching_with_rails.html#page-caching&quot;&gt;page caching&lt;/a&gt;. Here’s how we do it.&lt;/p&gt;

&lt;h4 id=&quot;what-is-csrf-protection&quot;&gt;What is CSRF protection?&lt;/h4&gt;

&lt;p&gt;CSRF protection allows us to ensure our users do not become the victims of cross-site forgery attacks.&lt;/p&gt;

&lt;p&gt;Here’s a simple example:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You’re browsing the internet, while logged into your Mixlr account&lt;/li&gt;
  &lt;li&gt;You inadvertedly visit a malicious or infected website&lt;/li&gt;
  &lt;li&gt;The malicious site uses JavaScript to make a POST request to (for example) mixlr.com/comments - our endpoint for incoming chat messages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With no CSRF protection, the malicious site only has to figure out the format to POST the data. &lt;em&gt;No authentication is required, because your browser will helpfully include your mixlr.com session and login cookies with the request!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With no further user interaction required, the malicious site is hapilly posting one or more chat messages from your Mixlr account. (And doubtless “helping” the rest of our community with the location of dubious mens’ health shopping portals and the like.)&lt;/p&gt;

&lt;p&gt;CSRF protection typically avoids this by including a hidden, secret value in every form submission. This value - the &lt;strong&gt;form authenticity token&lt;/strong&gt; - is checked by the server before any non-GET request is processed. And because the malicious website could not know the value of a given user’s secret token, it renders this type of attack completely toothless.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/token.png&quot; alt=&quot;The form authenticity token seen in the wild&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;what-is-page-caching&quot;&gt;What is page caching?&lt;/h4&gt;

&lt;p&gt;Page caching is a powerful way of increasing the scalability of your web service. It works on the premise that serving a static file - that is, a page of pre-rendered HTML markup - is likely to be profoundly faster than using a language like PHP, Ruby or Python to generate the same content.&lt;/p&gt;

&lt;p&gt;It turns out that this premise is an entirely valid one - as a rule, cutting out the roundtrip to backend web servers, database, et al allows us to serve many hundreds times more concurrent page views than we’d be able to without page caching.&lt;/p&gt;

&lt;p&gt;The limitation with page caching is the obvious one. As we’re short-circuiting the backend web servers, it’s only good for non-dynamic content - that is, content you’re prepared to be served without modification to every user, whether they’re logged in or not.&lt;/p&gt;

&lt;p&gt;#### Why CSRF protection and page caching clash&lt;/p&gt;

&lt;p&gt;Which leads us nicely onto why these two desirable technologies don’t work well together.&lt;/p&gt;

&lt;p&gt;CSRF protection requires a unique-per-user token to be included in each page. But page caching makes this, at least on the surface, impossible - because dynamic content in each page cannot be achieved.&lt;/p&gt;

&lt;h4 id=&quot;option-1-server-side-includes&quot;&gt;Option 1: Server-side includes&lt;/h4&gt;

&lt;p&gt;For many years, we’ve &lt;a href=&quot;https://www.nginx.com/resources/wiki/modules/lua/&quot;&gt;embedded Lua into the Nginx server&lt;/a&gt; to help us to turbo-charge our deployments.&lt;/p&gt;

&lt;p&gt;This also helped us make page caching and CSRF work together. Specifically, we made use of SSI, or &lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_ssi_module.html&quot;&gt;server-side includes&lt;/a&gt;. These are effectively small templates which are injected by Nginx into every page - even cached ones.&lt;/p&gt;

&lt;p&gt;With the help of some custom Lua code, which made a sub-request to a very fast, efficient Rails endpoint when required to fetch a new CSRF token, we were able to serve tens of thousands of cached responses every second - and include a unique CSRF token in each and every one.&lt;/p&gt;

&lt;p&gt;While this solution was very clever and flexible, it came with some downsides too. Debugging Lua code at the Nginx level is difficult and counter-intuitive - and just &lt;em&gt;having&lt;/em&gt; code at the Nginx/Lua level is a bit surprising too! It’s not the first place you think of checking when you’ve got a login/CSRF bug.&lt;/p&gt;

&lt;p&gt;Furthermore, as we’ve incrementally improved our session management and authentication code, we’ve observed more and more bugs which were traced back to this code. So we went looking for a different approach.&lt;/p&gt;

&lt;h4 id=&quot;option-2-ajax&quot;&gt;Option 2: AJAX&lt;/h4&gt;

&lt;p&gt;Another option would be to not render a CSRF token in each page, but instead use JavaScript to make a background HTTP request and fetch the CSRF token after the page has loaded.&lt;/p&gt;

&lt;p&gt;This would allow us to cache the main content on the page, but then trigger a background request to fetch the CSRF token for the user.&lt;/p&gt;

&lt;p&gt;The advantage here is that it allows us to remove the custom Nginx/Lua code, and keep this essential functionality upfront and visible in our codebase. On the downside, there will be a delay after loading the page during which the user will be unable to successfully submit any forms. And if the request to fetch the CSRF token fails for some reason, any such form submissions will fail at least until the page is reloaded.&lt;/p&gt;

&lt;h4 id=&quot;our-current-solution&quot;&gt;Our current solution&lt;/h4&gt;

&lt;p&gt;We want to avoid as much code at the Nginx level as possible, so we’ve made the call to remove our implementation of Option 1.&lt;/p&gt;

&lt;p&gt;Additionally, we want to make our lives as easy as possible - so for all non-cached responses (that is - where the page generation is handled by our backend Rails servers) - we’re allowing the framework to take the strain. In these cases, we simply allow Rails’ &lt;a href=&quot;http://api.rubyonrails.org/classes/ActionView/Helpers/CsrfHelper.html&quot;&gt;built-in CSRF token helpers&lt;/a&gt; do the work, and render the token in the page for us.&lt;/p&gt;

&lt;p&gt;How do we deal with page-cached responses? Firstly, we make sure that we &lt;em&gt;don’t&lt;/em&gt; include the CSRF token when we’re caching a page.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/rfwatson/53d20c52475a5d39a2de.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;And then in our controller, something like:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/rfwatson/2c5468883ebe59fc770a.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Now, Nginx will serve page-cached content with the invalid form authenticity token removed.&lt;/p&gt;

&lt;p&gt;In our front-end code, we simply check to see if we’re missing a CSRF token - that is, if the page we’re on has been served from a static file - and if so, make a quick XHR request to pick up the token, populate the forms and set the session cookie.&lt;/p&gt;

&lt;p&gt;Job done!&lt;/p&gt;

&lt;h4 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h4&gt;

&lt;p&gt;We’d love to hear your feedback, or suggestions for improvements to our approach. &lt;a href=&quot;http://mixlr.com/help/contact&quot;&gt;Drop us a line&lt;/a&gt; and let us know what you think!&lt;/p&gt;
</description>
        <pubDate>Mon, 25 Jan 2016 14:00:00 +0000</pubDate>
        <link>http://tech.mixlr.com/development/2016/01/25/how-to-handle-csrf-token-when-page-caching.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/development/2016/01/25/how-to-handle-csrf-token-when-page-caching.html</guid>
        
        <category>csrf,</category>
        
        <category>page</category>
        
        <category>caching</category>
        
        
        <category>development</category>
        
      </item>
    
      <item>
        <title>Welcome to Mixlr Tech Blog</title>
        <description>&lt;p&gt;Welcome to the Mixlr technology blog, where we will be sharing some of what we learn every day while building Mixlr’s back-end and front-end systems and apps.&lt;/p&gt;

&lt;p&gt;Right now, we’re hiring for Ruby on Rails, C/C++ and DevOps engineers here in London. If you want to find out more information, &lt;a href=&quot;mailto:jobs@mixlr.com&quot;&gt;drop us a line&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/downloads/RailsDevelopers2015.pdf&quot;&gt;&lt;img src=&quot;/images/rails.png&quot; style=&quot;width:250px;border:1px solid #aaa;margin-top:10px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 14 May 2015 14:22:27 +0000</pubDate>
        <link>http://tech.mixlr.com/welcome/2015/05/14/welcome-to-mixlr-techblog.html</link>
        <guid isPermaLink="true">http://tech.mixlr.com/welcome/2015/05/14/welcome-to-mixlr-techblog.html</guid>
        
        
        <category>welcome</category>
        
      </item>
    
  </channel>
</rss>
