<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Guillaume Voisin on Medium]]></title>
        <description><![CDATA[Stories by Guillaume Voisin on Medium]]></description>
        <link>https://medium.com/@voising?source=rss-7b6e66488e2d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Qzv9VvKEoWStdwO6PF-Ukw.jpeg</url>
            <title>Stories by Guillaume Voisin on Medium</title>
            <link>https://medium.com/@voising?source=rss-7b6e66488e2d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 12:57:03 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@voising/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[How Crystal Performs Compared to Ruby —  Filtering Module for Marketplace]]></title>
            <link>https://medium.com/@voising/how-crystal-performs-compared-to-ruby-filtering-module-for-marketplace-3349277f5771?source=rss-7b6e66488e2d------2</link>
            <guid isPermaLink="false">https://medium.com/p/3349277f5771</guid>
            <category><![CDATA[crystal-lang]]></category>
            <category><![CDATA[marketplace-software]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Guillaume Voisin]]></dc:creator>
            <pubDate>Thu, 14 Nov 2019 14:09:14 GMT</pubDate>
            <atom:updated>2019-11-14T17:58:10.341Z</atom:updated>
            <content:encoded><![CDATA[<h3>How Crystal Performs Compared to Ruby — Filtering Module for Marketplace</h3><p>To put things in context, I and my partner are launching a <strong>marketplace</strong> <strong>for babysitters</strong> soon in Budapest, Hungary.</p><p><strong>Current open-source marketplaces don’t fit our expectations</strong>. We need a marketplace that is both very fast and good looking. We also need the code to be flexible enough to add custom features quickly.</p><p><strong>Hence I decided to build it from scratch</strong>. To have a great UX, I’ll rely on <a href="https://vuejs.org/">Vue.js</a> and I’ll code the backend using Ruby on Rails.<br>The app will be a monolith where NGINX passes requests to either a Rails or Crystal server.<br>I chose <a href="https://rubyonrails.org/">Rails</a> for fast-paced development and <a href="https://crystal-lang.org/">Crystal</a> for performance (using <a href="https://amberframework.org/">Amber</a>).</p><h3>Building the filtering module — Crystal vs Ruby</h3><p>I coded the filtering module both in Crystal and Ruby. I’d like to share with you how it impacts the performances and the user experience.</p><h4>A quick look at the UI/UX</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fq3nSpYOE4Po%3Ffeature%3Doembed&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dq3nSpYOE4Po&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fq3nSpYOE4Po%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ae13baa8c07970826ffdac055629d632/href">https://medium.com/media/ae13baa8c07970826ffdac055629d632/href</a></iframe><h4>Ruby version</h4><p>Controller:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9eef9b7d8d96dd90c309f91ac51bb1f0/href">https://medium.com/media/9eef9b7d8d96dd90c309f91ac51bb1f0/href</a></iframe><p>Model:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fa6ffb8c5301f2220342bd564877ffa1/href">https://medium.com/media/fa6ffb8c5301f2220342bd564877ffa1/href</a></iframe><h4>Crystal version</h4><p>Controller:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/63b0bd48477e676e97aec42169dfd718/href">https://medium.com/media/63b0bd48477e676e97aec42169dfd718/href</a></iframe><p>Model:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fb908c74bb0902adac7a8d76e2c4e47f/href">https://medium.com/media/fb908c74bb0902adac7a8d76e2c4e47f/href</a></iframe><h3>How it performs</h3><h4>HTTP GET that returns 25 items</h4><ul><li><strong>Ruby (Ruby on Rails): </strong>21ms</li><li><strong>Crystal (Amber): </strong>9.7ms</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nc3AfhWhBvDNy8hfSpZrTg.jpeg" /><figcaption>25 results</figcaption></figure><h4>HTTP GET that returns 100 items</h4><ul><li><strong>Ruby (Ruby on Rails): </strong>32ms</li><li><strong>Crystal (Amber): </strong>16ms</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H4oRkwH0hISQldrN87UfuQ.jpeg" /><figcaption>100 results</figcaption></figure><h4>HTTP GET that returns 500 items</h4><ul><li><strong>Ruby (Ruby on Rails): </strong>114ms<br>At this size of the query, we start to feel a bit of lag.</li><li><strong>Crystal (Amber): </strong>33.12ms</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*b_f2Wbt4uYdrPSx9NJEKRQ.jpeg" /><figcaption>500 results</figcaption></figure><h4>Summary</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1bc5019cc4d8de402697b41d84c0658a/href">https://medium.com/media/1bc5019cc4d8de402697b41d84c0658a/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=%2F%2Fembed.chartblocks.com%2F1.0%2F%3Fc%3D5dcba4f23ba0f6592f68c88c%26t%3De2d7fa30e227e16&amp;url=https%3A%2F%2Fpublic.chartblocks.com%2Fc%2F5dcba4f23ba0f6592f68c88c%3Ft%3De2d7fa30e227e16&amp;image=https%3A%2F%2Fwww.gravatar.com%2Favatar%2Ff54cc485174b716d93072956bb5b4e2c%3Fd%3Dmm&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=chartblocks" width="800" height="450" frameborder="0" scrolling="no"><a href="https://medium.com/media/7f63118ee8f29c57c436fe7b4575c19e/href">https://medium.com/media/7f63118ee8f29c57c436fe7b4575c19e/href</a></iframe><h3>Conclusion</h3><p>In that context, Ruby on Rails gets slow above 400 items, but that’s not a big problem. We just have to chunk the result into sets of 50 items, load content when the user scrolls and that does the trick, we’re below 50ms.</p><p>Amber offers excellent performance, we can use the same strategy (add a LIMIT 50, paginate) and stay below 15ms for every query! That’s great! :)</p><p>I hope this quick comparison was useful to you and maybe gave you the will to try Crystal ;). Crystal can be very useful for long <a href="https://github.com/mperham/sidekiq.cr">sidekiq jobs</a> or HTTP queries that can’t be cached.</p><p>Thanks for reading!</p><p>By the way, I work as an independent contractor, feel free to <a href="https://twitter.com/voising">contact me</a> if you need to get a marketplace done.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3349277f5771" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>