<?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:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Georgi N. Georgiev - SashiDo.io | API Development, Deployment and Scaling made simple.]]></title><description><![CDATA[SashiDo.io is a serverless API development platform with scalable json rest and graphql apis, headless cms, built with nodejs, mongodb, parse server, kubernetes and docker.]]></description><link>https://blog.sashido.io/</link><image><url>https://blog.sashido.io/favicon.png</url><title>Georgi N. Georgiev - SashiDo.io | API Development, Deployment and Scaling made simple.</title><link>https://blog.sashido.io/</link></image><generator>Ghost 1.20</generator><lastBuildDate>Tue, 26 May 2026 05:01:43 GMT</lastBuildDate><atom:link href="https://blog.sashido.io/author/gngeorgiev/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Fearlessly upgrading your SashiDo app from Parse Server v2 to v3]]></title><description><![CDATA[See how you can fearlessly upgrade to the latest Parser Server Version v3.1.3 on SashiDo. Along with the latest version, we're also introducing v2.8.4 and v.3.0.0, so we can give you an incremental approach to upgrade which will even further reduce risks and guarantee the smooth transition. And to cast away worries and fears of the breaking changes you all have heard about, SashiDo put on exclusively for its customers a Cloud Code compatibility layer. ]]></description><link>https://blog.sashido.io/fearlessly-upgrading-your-sashido-app-from-parse-server-v2-to-v3/</link><guid isPermaLink="false">5c9a1c36c67ad20016e0eb85</guid><category><![CDATA[Parse Server]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Cloud Code]]></category><dc:creator><![CDATA[Georgi N. Georgiev]]></dc:creator><pubDate>Tue, 02 Apr 2019 14:02:01 GMT</pubDate><media:content url="https://media-blog.sashido.io/content/images/2019/03/parse-server-upgrade-v2-to-v3.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><h2 id="preface">Preface</h2>
<img src="https://media-blog.sashido.io/content/images/2019/03/parse-server-upgrade-v2-to-v3.png" alt="Fearlessly upgrading your SashiDo app from Parse Server v2 to v3"><p>Not so long ago a new major version of Parse Server was released. Version 3 includes some pretty rough <a href="https://github.com/parse-community/parse-server/blob/master/CHANGELOG.md#300">breaking changes</a> when it comes to the Cloud Code and the JavaScript SDK -</p>
<ul>
<li>Version 2 of the Parse JavaScript SDK that is used in the Cloud Code lacks some methods on the <strong>ParsePromise</strong> type, as described <a href="https://github.com/parse-community/Parse-SDK-JS/blob/master/2.0.0.md">here</a>. Luckily, replacing these methods should be fairly easy since the native <strong>Promises</strong> are supported in all Parse Server versions on <em>SashiDo</em>. In fact, these should be one of the first changes to perform before upgrading your Parse Server version.</li>
<li>Cloud Code handlers have a new interface based on promises.</li>
<li><strong>response.success</strong> / <strong>response.error</strong> are removed in Cloud Code</li>
</ul>
<p>In short this means that the following code that works on version 2.x.x will no longer work:</p>
<pre><code class="language-js">Parse.Cloud.define('fetch_data', (req, res) =&gt; {
    externalService.fetch()
      .then(data =&gt; res.success(data))
      .catch(err =&gt; res.error(err));
});
</code></pre>
<p>And will have to be replaced with the following code:</p>
<pre><code class="language-js">Parse.Cloud.define('fetch_data', req =&gt; externalService.fetch());
</code></pre>
<h2 id="theproblems">The problems</h2>
<p>Something is bugging you with the above? Let me reiterate, so we are on the same page... Breaking change means that you will have to change your <em>whole</em> cloud code and redeploy it, at the same time you need to change the version of your Parse Server to match the new cloud code <em>and</em> all of this without interrupting your backend's ability to serve your app’s users. That's why SashiDo has something special in store for its customers, keep reading!</p>
<p>We, at SashiDo also recognize that the version(2.3.3) of your SashiDo applications is not quite up to date and a smooth transition will be required. Since no software is perfect and incompatibilities are always in the realm of possibilities when changing versions, we would like to reduce the risks during the transition as much as we can. That's why we are releasing a total of <em>3 versions</em> alongside <em>2.3.3</em> so you can incrementally upgrade your app. The versions are:</p>
<ul>
<li>2.8.4</li>
<li>3.0.0</li>
<li>3.1.3</li>
</ul>
<h2 id="thewayahead">The way ahead</h2>
<p>So, you want to upgrade your Parse Server to the latest version? Great! Here's what we recommend you to do.</p>
<p>First and foremost, we highly recommend for any production apps to be tested on a development version of themselves before upgrading. To do that, we recommend effectively cloning your existing application, which consists of the following steps:</p>
<ol>
<li>Create a new application from the <a href="https://dashboard.sashido.io">Sashido Dashboard</a>.</li>
<li>Export the database from your production application and import it into the database of your newly created application. Here's a useful video on how to do that: <a href="https://www.youtube.com/watch?v=s7I54slFPLY&amp;index=19&amp;list=PLk66IKYX7bjrBKSNwNZVpTjVswA0oq5dr">Database import &amp; export</a></li>
<li>Start the new app's Cloud Code and copy it over from your production application's GitHub repo to the new one. Optionally, you can also add your new app's GitHub repo as a new remote to your local repo, for easier development. More info on the topic here <a href="https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes">Git Basics - Working with Remotes</a>.</li>
<li>Push the changes to GitHub.</li>
</ol>
<p>Now that you have a clone of your application, select it in the Dashboard, go to <strong>Runtime -&gt; Parse Server Version</strong> and set your version to <em>2.8.4</em>. After your application has been rebuilt, make sure that everything is running okay. Check the logs for errors, run cloud code requests, run Parse queries, whatever defines your application as <strong>operational</strong>.</p>
<p>At this point, you have not modified your Cloud Code. Now would be the right moment, to verify that your <strong>Parse Server</strong> is working as expected with version <em>2.8.4</em>. After the extensive testing is done and you are sure that <em>2.8.4</em> looks good, you can switch your production application to it as well.</p>
<h2 id="fearlessupgrades">Fearless upgrades</h2>
<p>Alright, so we established that version <em>3.x</em> of the Parse Server brings some breaking changes, we also mentioned that SashiDo has put some sort of compatibility layer for you. Let me explain that real quick.</p>
<p>In the latest version of the Parse Server, the Cloud Function handlers don't receive a second argument when called. The second argument was holding the <strong>success</strong> and <strong>error</strong> functions which would signal that a certain function invocation has either succeeded or failed at a given point in time, maybe immediately, maybe in 5 seconds. We should now use promises and <strong>async/await</strong> to handle asynchronous functions, such as the following example, taken from the <a href="https://docs.parseplatform.org/cloudcode/guide/#cloud-functions">Parse Docs</a>:</p>
<pre><code class="language-js">// The new way
Parse.Cloud.define(&quot;averageStars&quot;, async (request) =&gt; {
  const query = new Parse.Query(&quot;Review&quot;);
  query.equalTo(&quot;movie&quot;, request.params.movie);
  const results = await query.find();
  let sum = 0;
  for (let i = 0; i &lt; results.length; ++i) {
    sum += results[i].get(&quot;stars&quot;);
  }
  return sum / results.length;
});
</code></pre>
<p>This is great, it truly is. <strong>async/await</strong> makes JavaScript code much more readable and easier to reason about. Moreover, unhandled exceptions will now be caught and returned to the caller properly, without requiring explicit error handling in 100% of the cases. However, if you have <em>1500 lines of Cloud Code</em>, upgrading it all in one go is probably not something you eagerly look forward to. That's why, in SashiDo you can have Cloud Code written in both styles - the new one (example above) and the old one:</p>
<pre><code class="language-js">// The old way
Parse.Cloud.define(&quot;averageStars_old&quot;, (request, response) =&gt; {
  const query = new Parse.Query(&quot;Review&quot;);
  query.equalTo(&quot;movie&quot;, request.params.movie);
    query.find()
    .then(results =&gt; {
        let sum = 0;
        for (let i = 0; i &lt; results.length; ++i) {
          sum += results[i].get(&quot;stars&quot;);
        }
        response.success(sum / results.length);    
      })
      .catch(err =&gt; response.error(err));
});
</code></pre>
<p>Basically, all apps in SashiDo will have a <a href="https://github.com/cloudstrap/sashido-parse-cloud-code-compatibility-layer">compatibility layer</a> injected into their Cloud Code for versions after <em>3.x</em>. Which will eliminate the breaking changes, allowing you to migrate your Cloud Code at a steady and comfortable pace. At the end of the day, you get all the new features and in return, it doesn't cost a full application rewrite. That's a win in my book!</p>
<h2 id="finalsteps">Final steps</h2>
<p>Remember the routine we went through to verify that our application worked on version <em>2.8.4</em>? Yeah, me neither, refresh your memory <a href="https://blog.sashido.io/fearlessly-upgrading-your-sashido-app-from-parse-server-v2-to-v3#thewayahead">here</a>. When upgrading from <em>2.8.4</em> to <em>3.0.0</em> and <em>3.1.3</em> you need to follow the same steps. Only this time, after making sure that your application is operational you should start rewriting your Cloud Code functions one by one. We strongly recommend you do that since we can't guarantee the compatibility layer will allow you to take full advantage of all the Parse Server features in its next releases.</p>
<h2 id="theend">The End</h2>
<p>That's it. You should now be fully prepared to upgrade your SashiDo applications!</p>
<p>Cheers and enjoy! :)</p>
</div>]]></content:encoded></item><item><title><![CDATA[Announcing MicroCDN and SashiDo Files Service]]></title><description><![CDATA[<div class="kg-card-markdown"><p>For today's mobile applications and websites is essential to deliver a significant amount of static content to the end users. This content includes images, videos, documents and any other unique digital goods that modern businesses are producing. As these static assets grow in number and size, bandwidth usage swells and</p></div>]]></description><link>https://blog.sashido.io/announcing-microcdn-for-sashido-files/</link><guid isPermaLink="false">5b8ea7ec212a6000158b0290</guid><category><![CDATA[announcements]]></category><category><![CDATA[Files]]></category><category><![CDATA[Files Service]]></category><category><![CDATA[microCDN]]></category><dc:creator><![CDATA[Georgi N. Georgiev]]></dc:creator><pubDate>Thu, 25 Oct 2018 12:00:00 GMT</pubDate><media:content url="https://media-blog.sashido.io/content/images/2018/09/sashido-micro-cdn-announcement-cover.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://media-blog.sashido.io/content/images/2018/09/sashido-micro-cdn-announcement-cover.jpg" alt="Announcing MicroCDN and SashiDo Files Service"><p>For today's mobile applications and websites is essential to deliver a significant amount of static content to the end users. This content includes images, videos, documents and any other unique digital goods that modern businesses are producing. As these static assets grow in number and size, bandwidth usage swells and page load times increase, deteriorating the browsing experience for your users and reducing your servers' available capacity.</p>
<p>The primary challenges digital businesses are facing today is the latency and coverage of the mobile network. 3G or 4G networks make more than 70% of the mobile app's traffic.</p>
<p>To dramatically reduce page load times, improve performance, and reduce your bandwidth and infrastructure costs, you can implement a CDN, or content delivery network, to cache these assets across a set of geographically distributed servers.</p>
<h2 id="howsashidostoretheappsfiles">How SashiDo store the apps files</h2>
<p>As you're already aware, SashiDo is a complete managed service, and for that reason, it's our job to handle all the challenges about where our customers are storing their static content and how their apps deliver it to their end users.</p>
<p>To provide highly scalable and stable file storage and delivery solution for the Parse Servers we are hosting we saw that AWS S3 would be an excellent foundation for that challenge.</p>
<h2 id="whatiscdnforsashidofiles">What is µCDN for SashiDo Files</h2>
<p>Two years since we've launched the SashiDo Platform we decided that's time to change the way applications deliver their static assets and take it to another level.</p>
<p>When we started working on the new SashiDo Files Service and µCDN (MicroCDN) we set a couple of goals we must achieve.</p>
<ul>
<li>Performance</li>
<li>Better User Experience</li>
<li>Happy Customers</li>
</ul>
<h3 id="whysashidofilesservice">Why SashiDo Files Service</h3>
<p>A year ago we announced the <a href="https://blog.sashido.io/sending-milions-of-push-notifications-with-go-redis-and-nats/">SashiDo Push Notifications Service</a>, and we had a clear idea of what we want to achieve:</p>
<ul>
<li>Send push notifications as quickly as possible</li>
<li>No notification can be dropped, ever</li>
<li>Perform well under high loads and don't consume too many resources</li>
<li>Save as much as possible resources into the Parse Server containers.</li>
</ul>
<p>In other words with the SashiDo Push Notifications Service, every Parse Application hosted here can send Millions Push Notifications per minute while at the same it's handling API requests without any issues.</p>
<p>Following the same principles, the SashiDo Files Service was born. How we did this:</p>
<ul>
<li>Entirely written in <a href="https://golang.org/">Go</a> (Performance, Scalability, Efficiency)</li>
<li><a href="https://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html">Amazon S3 Transfer Acceleration</a> enabled by default</li>
<li>Deep integration with the <a href="https://tus.io/">TUS Protocol</a></li>
</ul>
<p><strong>As a result, we've achieved up to 3x better performance.</strong></p>
<h3 id="whycdn">Why µCDN</h3>
<p>With the SashiDo Files Service, we are uploading the files much faster now, but we were aware that this was only 50% of our goal. That's why we changed the way how we deliver the files from AWS S3 by adding a <strong>MicroCDN layer</strong> with <strong>microZones support</strong>.</p>
<iframe frameborder="0" class="juxtapose" width="100%" height="506" src="https://cdn.knightlab.com/libs/juxtapose/latest/embed/index.html?uid=a97b656e-b11b-11e8-9dba-0edaf8f81e27"></iframe>
<h3 id="zonesmicrozones">µZones (microZones)</h3>
<p>Today our Parse Server infrastructure is running on four continents around the globe. Following the same concept, we've launched four microZones that will handle the files delivery based on where your Parse Server is hosted.</p>
<p>For example, if your Parse Server is hosted in our infrastructure Europe, your files will be delivered by the Europe mircoZone and etc.</p>
<p><strong>These are the SashiDo's microZones:</strong></p>
<ul>
<li>
<p><strong>Europe µZone:</strong> Amsterdam, Frankfurt, London, Luxembourg, Bucharest, Paris</p>
</li>
<li>
<p><strong>Americas µZone:</strong> Seattle, Phoenix, Miami, Chicago, Denver, New York, Dallas, Ashburn, Los Angeles, Palo Alto, San Jose, Toronto, Montreal, Sao Paulo</p>
</li>
<li>
<p><strong>Asia µZone:</strong> Tokyo, Singapore, Hong Kong, Chennai, Hyderabad</p>
</li>
<li>
<p><strong>Australia µZone:</strong> Sydney</p>
</li>
</ul>
<h2 id="howtoenablethisfeatureandhowmuchdoesitcost">How to enable this feature and how much does it cost?</h2>
<p>The SashiDo Files Service + µCDN is <strong>enabled by default</strong> for every application hosted on SashiDo <strong>for FREE</strong>!</p>
<h2 id="fin">Fin</h2>
<p>We hope that this significant change in our files delivery architecture will improve your customers' experience and will drastically increase  your revenue.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Debugging your SashiDo app's Cloud Code]]></title><description><![CDATA[<div class="kg-card-markdown"><p>So, you have created your SashiDo app, <a href="https://blog.sashido.io/how-to-set-up-cloud-code-on-sashido/">set up some cloud code</a> and are now wondering what would be the best way to test it. Of course, one of the obvious solutions would be to do a <code>git push</code> every time, then test it through the <a href="https://blog.sashido.io/introducing-the-api-console/">API Console</a>, another REST</p></div>]]></description><link>https://blog.sashido.io/debugging-your-sashido-apps-cloud-code/</link><guid isPermaLink="false">5b64f617bc278c0015f80300</guid><category><![CDATA[Cloud Code]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[debugging]]></category><dc:creator><![CDATA[Georgi N. Georgiev]]></dc:creator><pubDate>Mon, 13 Aug 2018 12:00:00 GMT</pubDate><media:content url="https://media-blog.sashido.io/content/images/2018/08/how-to-debug-sashido-apps-cloudcode-cover-3.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://media-blog.sashido.io/content/images/2018/08/how-to-debug-sashido-apps-cloudcode-cover-3.jpg" alt="Debugging your SashiDo app's Cloud Code"><p>So, you have created your SashiDo app, <a href="https://blog.sashido.io/how-to-set-up-cloud-code-on-sashido/">set up some cloud code</a> and are now wondering what would be the best way to test it. Of course, one of the obvious solutions would be to do a <code>git push</code> every time, then test it through the <a href="https://blog.sashido.io/introducing-the-api-console/">API Console</a>, another REST client, or your app directly. However, you and I both know that there has to be a better way, right?</p>
<h2 id="runalocalinstanceofparseserver">Run a local instance of Parse Server</h2>
<p>Running a local instance of the Parse Server with your Cloud Code is the first step you should take as it will allow you to iterate on your app much faster and consequently allow us to debug it. Here's how:</p>
<h3 id="1clonethesourceofyourapp">1. Clone the source of your app</h3>
<p>You can go to your GitHub profile and find the repo of your app. It will be something like <strong>pg-app-your-app-id</strong>, or you can just use the link from the SashiDo Dashboard.</p>
<p><img src="https://media-blog.sashido.io/content/images/2018/08/ezgif-5-6cef200d78.gif" alt="Debugging your SashiDo app's Cloud Code"></p>
<p>After you have the repo URL just run the following command in a terminal to clone the source:</p>
<p><img src="https://media-blog.sashido.io/content/images/2018/08/1-clone.gif" alt="Debugging your SashiDo app's Cloud Code"></p>
<p>This will download your app's source to a folder named <strong>my-sahido-app</strong>, change that to match your actual app name.</p>
<h3 id="2installthenpmmodulesofyourapp">2. Install the npm modules of your app</h3>
<p>This will require you to have <strong>node.js</strong> and <strong>npm</strong> installed on your system. We recommend <strong>node.js v8.6.0</strong> as this is the version SashiDo uses, but later versions should work too.</p>
<p><img src="https://media-blog.sashido.io/content/images/2018/08/2-npm-install.gif" alt="Debugging your SashiDo app's Cloud Code"></p>
<h3 id="3openthedirectoryinyourfavoriteeditoride">3. Open the directory in your favorite Editor/IDE</h3>
<p>Preferably, it should support Node.js debugging. In this article, we will use Visual Studio Code but others, such as WebStorm work just as well.</p>
<h4 id="31configureyourlocalparseserver">3.1. Configure your local Parse Server</h4>
<p>Open <strong>index.js</strong>, where you will see the Parse Server configuration. Keep in mind that this configuration will <strong>only</strong> affect your local Parse Server. It will look something like this:</p>
<pre><code class="language-javascript">var port = process.env.PORT || 1337;
var api = new ParseServer({
    databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
    appId: process.env.APP_ID || 'appId',
    masterKey: process.env.MASTER_KEY || 'masterKey',
    serverURL: process.env.SERVER_URL || 'http://localhost:' + port + '/1',
    cloud: process.env.CLOUD_CODE_MAIN || 'cloud/main.js',

    liveQuery: {
        classNames: []
    }
});
</code></pre>
<p>Here, you can change things like your <strong>Application Id</strong> and <strong>Master Key</strong>. You will be running this Parse instance only locally, but it's still a good practice to change your <strong>Master Key</strong>. It's also recommended to run a local instance of MongoDB, here's a good tutorial from the MongoDB docs - <a href="https://docs.mongodb.com/manual/tutorial/manage-mongodb-processes/">Manage MongoDB processes</a>. In case you want to use the same data as your SashiDo app, you can simply import it in your local MongoDB. We have a great tutorial on that - <a href="https://www.youtube.com/watch?v=s7I54slFPLY">Database import &amp; export</a>.</p>
<h4 id="32runit">3.2. Run it</h4>
<p>After you have set it all up, it's time to run the Parse Server.:</p>
<p><img src="https://media-blog.sashido.io/content/images/2018/08/3-npm-install.gif" alt="Debugging your SashiDo app's Cloud Code"></p>
<h4 id="33checkit">3.3. Check it</h4>
<p>Check that everything is working as expected by running:</p>
<p><img src="https://media-blog.sashido.io/content/images/2018/08/4-curl.gif" alt="Debugging your SashiDo app's Cloud Code"></p>
<p>By the way, this is how the code for connecting a JavaScript SDK instance to your local server looks like, in case you would want to test some queries or test your mobile app. Note that to connect to your local Parse Server, you don’t need a JavaScript key, because by default it’s not initialized with one. When connecting to SashiDo, you will need one as per the instructions in <strong>Dashboard &gt; Your app &gt; Getting Started</strong>.</p>
<pre><code class="language-javascript">Parse.initialize('appId');
Parse.masterKey = 'masterKey';
Parse.serverURL = 'http://localhost:1337/1/';
</code></pre>
<h2 id="debugyourcloudcode">Debug your cloud code</h2>
<p>Alright, so we have started our local instance of the Parse Server, but what about the debugging part?</p>
<p>You have two options. The first one is to utilize <code>console.info</code>, <code>console.warn</code> and <code>console.error</code>. This is perfectly fine for most cases, but sometimes you might need to debug a more complex scenario, where the console just doesn't cut it. In such scenarios, you can use <a href="https://nodejs.org/en/docs/guides/debugging-getting-started/">Node.js' debugging capabilities</a>. The debugger will allow you to inspect variables, step through code and evaluate expressions on the fly. You can watch the video <a href="https://www.youtube.com/watch?v=2oFKNL7vYV8">Getting started with Node.js debugging in VS Code</a> for more detailed information.</p>
<p>As mentioned above, we will use Visual Studio Code for this example, however, if VSCode is not your cup of tea, the process is mostly the same for other Editors/IDEs.</p>
<p>You should have already opened your project in your editor.  Now, click the buttons as shown in the picture below:</p>
<p><img src="https://media-blog.sashido.io/content/images/2018/08/1-vscode.png" alt="Debugging your SashiDo app's Cloud Code"></p>
<p>This will open a JSON file containing the following code:</p>
<pre><code class="language-javascript">{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    &quot;version&quot;: &quot;0.2.0&quot;,
    &quot;configurations&quot;: [
        {
            &quot;type&quot;: &quot;node&quot;,
            &quot;request&quot;: &quot;launch&quot;,
            &quot;name&quot;: &quot;Launch Program&quot;,
            &quot;program&quot;: &quot;${workspaceFolder}/index.js&quot;
        }
    ]
}
</code></pre>
<p>You don't need to change anything here, VSCode generated by default, a debugger configuration that runs <strong>index.js</strong>, which is the entry point of our application. Now, we can create a simple cloud function just to test our debugger:</p>
<pre><code class="language-javascript">Parse.Cloud.define('test', (req, res) =&gt; {
    console.log(req.params);
    res.success();
});
</code></pre>
<p>Run the following curl command to invoke the function from our terminal:</p>
<pre><code class="language-bash">curl --request POST \
  --url http://localhost:1337/1/functions/test \
  --header 'content-type: application/json' \
  --header 'x-parse-application-id: myAppId' \
  --data '{
        &quot;myparam&quot;: &quot;myvalue&quot;
}'
</code></pre>
<p>After this, all that is left to do is place a breakpoint inside the function and run the debugger as shown on the gif below.</p>
<p><img src="https://media-blog.sashido.io/content/images/2018/08/debug-1.gif" alt="Debugging your SashiDo app's Cloud Code"></p>
<h2 id="relatedresources">Related resources</h2>
<ol>
<li><a href="https://nodejs.org/en/docs/guides/debugging-getting-started/">Node.js' debugging capabilities</a></li>
<li><a href="https://www.youtube.com/watch?v=2oFKNL7vYV8">Getting started with Node.js debugging in VS Code</a></li>
<li><a href="https://www.youtube.com/watch?v=Xb_0awoShR8">Debugging in 2017 with Node.js</a></li>
</ol>
<h2 id="theend">The end</h2>
<p>Hopefully, after this, you will be able to debug your applications a little more easily and develop cool stuff even faster than before!</p>
</div>]]></content:encoded></item><item><title><![CDATA[Zero downtime migration from Telerik Platform to SashiDo]]></title><description><![CDATA[We know moving from one backend to another is not an easy process. With enough migrations behind our back, we will help you migrate with zero downtime. ]]></description><link>https://blog.sashido.io/zero-downtime-migration-from-telerik-platform-to-sashido/</link><guid isPermaLink="false">5a5dc99c34405f92e87fbd6f</guid><category><![CDATA[Tutorial]]></category><category><![CDATA[migration]]></category><dc:creator><![CDATA[Georgi N. Georgiev]]></dc:creator><pubDate>Tue, 09 Jan 2018 13:18:22 GMT</pubDate><media:content url="https://media-blog.sashido.io/content/images/2018/01/cover-3.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://media-blog.sashido.io/content/images/2018/01/cover-3.png" alt="Zero downtime migration from Telerik Platform to SashiDo"><p>Migrating from one backend to another is not an easy process and we know it. With enough migrations behind our back, <strong>SashiDo</strong> is here to help. By the time Telerik Platform closes its doors in <strong>May 2018</strong>, you should have already migrated your data, business logic and front end, etc. to another backend. We have covered that up in <a href="https://blog.sashido.io/checklist-for-successful-telerik-platform-migration/">Checklist for successful Telerik Platform migration</a>. When that happens their services will no longer respond, which would render any application using them - useless. Here's what you can do:</p>
<h3 id="prepareearlyon">Prepare early on</h3>
<p>There's a saying &quot;Luck favors the prepared&quot;, but we don't want to leave anything to luck right? Since there are a few more months left until <strong>May</strong>, there's plenty of time to prepare. First of all, you would want to make your app aware that at some point it would have to start using your new backend of choice. That would be very easy and basic for the time being - just create a <strong>cloud function</strong> in your Telerik Platform backend. Let's call it <strong>canWeStartUsingSashidoAlready</strong> and have it return <em>false</em>. Now, you can add a check on app startup that calls this function. If it returns <em>false</em>, it will continue to work normally, otherwise, if it returns <em>true</em> the user is prompted to go to the AppStore and get the latest version. In the best case this check will also happen every 30 or 60 seconds, so users that didn't close the app get the prompt too. Since we are now prepared, let's move on to the next chapter of our migration journey.</p>
<pre><code class="language-javascript">Everlive.CloudFunction.onRequest(function (request, response, done) {
    response.body = false;
    done();
});
</code></pre>
<h3 id="startusingsashidoandparse">Start using SashiDo and Parse</h3>
<p>First, make sure to go through the checklist above, so that your backend is migrated to SashiDo. Next up, you would have to change your app to work with the Parse SDK. Our blog post <a href="https://blog.sashido.io/crash-course-with-parse-server-for-telerik-platform-developers-by-sashido/">Crash course with Parse Server for Telerik Platform developers</a> will be very useful here. This is the part for you where most of the work will happen. There's also a slight complication you might notice on this step. &quot;How would my users log into my app after the migration, passwords are encrypted?&quot; - you might ask. Don't worry we have it figured out for you. See, when we migrate your data from Telerik Platform to SashiDo, we set a field called <strong>shouldChangePasswordAfterMigration</strong> on each of your users, and it's <em>true</em> by default. Here's how it is gonna play out when a user goes to login with your new app:</p>
<ol>
<li>He would see the login page, because he doesn't have a valid session.</li>
<li>Upon entering his credentials and clicking login, your app, will check whether the field mentioned above is set to <em>true</em>.</li>
<li>If it is, the user is prompted to change his password. It’s recommended that a confirmation email is sent to the user, to keep security top notch.</li>
<li>After that, the field is set to <em>false</em> and the app continues to work as usual.</li>
</ol>
<pre><code class="language-javascript">Parse.Cloud.define('shouldChangePasswordAfterMigration', function(
    request,
    response
) {
    const { userID } = request.params;
    const query = new Parse.Query(Parse.User);
    query.equalTo('objectId', userID);
    query.first().then(user =&gt; {
        if (!user) {
            return response.success(false);
        }

        return response.success(
            !!user.get('shouldChangePasswordAfterMigration')
        );
    });
});
</code></pre>
<p>Alright, let's move along.</p>
<h3 id="deliveryournewapptotheusers">Deliver your new app to the users</h3>
<p>After we have set the check in the old version that would prompt the user to update when the <strong>canWeStartUsingSashidoAlready</strong> cloud function returns <em>true</em> and have a new app ready it can be released to the AppStore. After it's release, go to the Telerik Platform cloud code browser and set the cloud function to return <em>true</em>. Your customers will update their applications and won't even notice that you have switched to <strong>SashiDo</strong>. That is unless you add some cool functionality using our features of course, e.g. live queries.</p>
<h4 id="bonus">Bonus</h4>
<p>Since SashiDo allows you to have custom domains, you can have a subdomain like <strong>mobile-api.customdomain.com</strong> and if in the future you decide to switch Parse Server provider, you can just point the domain to your new hosting and everything will just work.</p>
<h3 id="success">Success</h3>
<p>You have successfully migrated your application. Maybe it's time to take that vacation? In any case, we will see you around.</p>
<p>Happy coding!</p>
</div>]]></content:encoded></item><item><title><![CDATA[Sending Millions Push Notifications per minute with Go, Redis and NATS]]></title><description><![CDATA[<div class="kg-card-markdown"><p>If you have sent push notifications with <em>Parse Server</em> you are probably familiar with the issues that come with having larger audience. The way the <em>Parse Server</em>'s push notifications work is the following: your <strong>Installations</strong> are fetched in batches, these batches are then sent respectively to <strong>FCM(Android)</strong> and/</p></div>]]></description><link>https://blog.sashido.io/sending-milions-of-push-notifications-with-go-redis-and-nats/</link><guid isPermaLink="false">5a5dc99b34405f92e87fbd6a</guid><category><![CDATA[announcements]]></category><category><![CDATA[Push Notifications]]></category><category><![CDATA[engineering]]></category><dc:creator><![CDATA[Georgi N. Georgiev]]></dc:creator><pubDate>Tue, 14 Nov 2017 17:56:00 GMT</pubDate><media:content url="https://media-blog.sashido.io/content/images/2017/11/cover-2-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://media-blog.sashido.io/content/images/2017/11/cover-2-1.png" alt="Sending Millions Push Notifications per minute with Go, Redis and NATS"><p>If you have sent push notifications with <em>Parse Server</em> you are probably familiar with the issues that come with having larger audience. The way the <em>Parse Server</em>'s push notifications work is the following: your <strong>Installations</strong> are fetched in batches, these batches are then sent respectively to <strong>FCM(Android)</strong> and/or <strong>APNS(iOS)</strong>.</p>
<p>One of the issues is that the progress of these batches is not tracked. Let’s say your application has 2 million installations, currently the <em>Parse Server</em> would take roughly <strong>5 to 10 minutes</strong> to send push notifications to all of them. In this time a number of things can happen to your <em>Parse Server</em>, e.g. it might crash or restart due to a new deployment. This would cause the process of sending push notifications to halt in an undefined state and some users will never receive the said notifications.</p>
<p>Moreover, the process is not distributed. This means that you can't take advantage of horizontal scaling because only one instance of your application is processing the workload at a time. Oh yeah, and lets face it, <strong>Node.js</strong> doesn't do really well under high loads.</p>
<h3 id="alternatives">Alternatives</h3>
<p>What were our options? We could</p>
<ul>
<li>Create a new <em>Parse Server</em> adapter to address the points above - That sounds like a good plug-and-play idea, but we would ultimately still be limited to <strong>Node.js</strong> and that wouldn't be ideal in the case of millions of Installations per application.</li>
<li>Use an external service, such as <strong>OneSignal</strong> or  <strong>Amazon SNS</strong> - That would be a good option, however each service has its own set of limitations and we would have to work around them. Also synchronizing Installations to the respective service alternative and getting detailed response for each notification would be far from ideal.</li>
<li>Create our own service - Have complete control over the whole process, which would allow us to provide great experience to our customers and also give us the opportunity to iterate over the solution further over time. This way we would also completely take the load off the <em>Parse Server</em>.</li>
</ul>
<h3 id="introducingsashidopushnotificationsservice">Introducing SashiDo Push Notifications Service</h3>
<p>We made our choice - create an external service that will be able to handle the demands of our customers. There are a few prerequisites that we had to meet:</p>
<ol>
<li>Send push notifications as quickly as possible</li>
<li>No notification can be dropped, ever</li>
<li>Stick to the <strong>SashiDo no vendor lock-in policy</strong> - we must not change the way the <em>Parse Server</em> is working. Should you choose to host your <em>Parse Server</em> somewhere else, the push notifications would continue working, just without the benefits described in this article</li>
<li>Perform well under high loads and don't consume too much resources</li>
<li>Be able to scale each component of the system according to demand</li>
<li>Keep database reads and writes within a tolerable range since we are using each Parse application's database (<strong>SashiDo no vendor lock-in policy</strong>, our customers own their data!)</li>
</ol>
<div class="push-banner">Get a Million of Push Notifications sent for FREE & delivered INSTANTLY to your users!
    <a class="btn green text" href="https://bit.ly/3nG83Ch">Try SashiDo Now<span>no vendor lock-in. no credit card</span></a>
</div>
<p>First of all a fitting language had to be chosen. We could choose from <strong>Rust</strong>, <strong>Go</strong> and maybe <strong>Elixir</strong>. Due to our domain knowledge with <strong>Go</strong>, that's what we picked. We all know what <strong>Go</strong> brings to the table with its great concurrency model and easy deployment, so I will not go deep into the rationale behind this choice. It suffices to say that we are very happy with the results. If you are not familiar with the language, here's a great article <a href="https://blog.learngoprogramming.com/about-go-language-an-overview-f0bee143597c">About Go Language  - An Overview</a>.&lt;/p?</p>
<p>To be able to scale each component of the system independently of course, we went with a microservice architecture. Interestingly enough, we started with only 2 microservices. Their numbers quickly began to grow and we ended up with a total of 8 microservices. Bellow, you can see a simplified schematic of the architecture.</p>
<p><img src="https://media-blog.sashido.io/content/images/2017/11/pushes_blog_post.png" alt="Sending Millions Push Notifications per minute with Go, Redis and NATS"></p>
<p>Let’s go through the workflow real quick. When a new push notification gets to the <em>Parse Server</em> it's sent to Push Notifications Service's REST API. This request, then gets to the <strong>Installations batchers</strong>, which is group of microservices that read <em>installations</em> from the respective application's database in batches. &quot;Why in batches?&quot; one would ask. There are two main reasons for that. First - we want to distribute the process across microservice instances for fault tolerance reasons and second - this allows us to control the amount of read items from the database at a time and per query. With this approach we are able to read millions of <em>installations</em> with no significant impact on the database. After each batch of <em>installations</em> is fetched, each <em>installation</em> is sent to a respective <strong>Sender</strong>. Currently, we have two senders - <strong>iOS</strong> and <strong>Android</strong>, which use <a href="https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html">APNS2</a> and <a href="https://firebase.google.com/docs/cloud-messaging/">FCM</a> respectively. And when each push is delivered to either <strong>APNS2</strong> or <strong>FCM</strong>, the response is passed to the <strong>Status workers</strong>. In a similar fashion as the <strong>Installation batchers</strong> they make sure not to stress the database too much while saving the statuses. This way we can scale the <strong>Senders</strong> as we see fit without worrying for the workload put on the database.</p>
<p>&quot;This is great but, what are <strong>Redis</strong> and <strong>NATS Streaming</strong> doing there?&quot; - Glad you asked. We are using <strong>Redis</strong> for caching of course, but not only. Each microservice uses <strong>Redis</strong> to store progress of its operations. This is to ensure that if an instance is to die unexpectedly or another failure occurs, the next one that handles the operation will continue from the same place.</p>
<p>Let me tell you the story behind why we chose to include <strong>NATS Streaming</strong> in our stack. For those of you who don't know <a href="https://nats.io/documentation/streaming/nats-streaming-intro/">NATS Streaming</a> is a data streaming system/message queue built on top of <a href="https://nats.io/documentation/server/gnatsd-intro/">NATS Server</a>. But why did we choose it? Well, it turns out when you want to have a message queue capable of processing 200 000 messages per second your options are kind of limited. For example, we tried with <strong>RabbitMQ</strong> at first, but quickly proved one of our expectations that reaching these numbers and having high availability would require some pretty solid hardware. For example, you can read a great article on how to reach 1 million messages per second with <strong>RabbitMQ</strong> by using 32 machines, 30 of which with 8 vCPUs and 30 GB of RAM - <a href="https://content.pivotal.io/blog/rabbitmq-hits-one-million-messages-per-second-on-google-compute-engine">RabbitMQ Hits One Million Messages Per Second on Google Compute Engine</a>. <strong>NATS Streaming</strong> on the other hand is simple, built with <strong>Go</strong> and crazy fast. One drawback is that it still doesn't support clustering, however our <strong>DevOps</strong> guys were able to cast some black magic to make it work with the fault tolerance capabilities it currently provides. The results? We were able to get out <strong>100 000 incoming</strong> and <strong>100 000 outgoing</strong> messages per second out of just <strong>3 VMs</strong>. We also saw <strong>NATS</strong> was very stable with high loads. Bellow you can see some stats from our tests.</p>
<p><img src="https://media-blog.sashido.io/content/images/2017/11/localhost_3000_dashboard-html.png" alt="Sending Millions Push Notifications per minute with Go, Redis and NATS"></p>
<p><img src="https://media-blog.sashido.io/content/images/2017/11/iptraf.jpg" alt="Sending Millions Push Notifications per minute with Go, Redis and NATS"></p>
<h3 id="results">Results</h3>
<p>After switching to the <strong>Push Notifications service</strong>, which is enabled by default with <em>Parse Server 2.3.3</em> on <strong>SashiDo</strong>, you will be able to send push notifications to your clients about <strong>20 times faster</strong> than before, without pushing the limits of your <em>Parse Server</em> and slowing down other requests. You will also no longer need to worry about restarts, crashes or deployments.</p>
<p>Read more about the new <em>Parse Server</em> version on <strong>SashiDo</strong> here: <a href="https://blog.sashido.io/our-new-parse-server-version-comes-with-new-service-for-push-notifications">Our new Parse Server Version comes with new service for Push Notifications</a></p>
<p>Happy pushing!</p>
<div class="push-banner">Get a Million of Push Notifications sent for FREE & delivered INSTANTLY to your users!
    <a class="btn green text" href="https://bit.ly/3nG83Ch">Try SashiDo Now<span>no vendor lock-in. no credit card</span></a>
</div></div>]]></content:encoded></item></channel></rss>