<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Md. Ishtiaque Zafar</title>
    <description>The latest articles on Forem by Md. Ishtiaque Zafar (@ishtiaque).</description>
    <link>https://forem.com/ishtiaque</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F351710%2Faca91490-5c9f-45b3-ab81-b18a753d1e2a.png</url>
      <title>Forem: Md. Ishtiaque Zafar</title>
      <link>https://forem.com/ishtiaque</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ishtiaque"/>
    <language>en</language>
    <item>
      <title>How to stay one step ahead of errors and downtime as you scale up your business</title>
      <dc:creator>Md. Ishtiaque Zafar</dc:creator>
      <pubDate>Thu, 06 Oct 2022 14:13:20 +0000</pubDate>
      <link>https://forem.com/finnauto/how-to-stay-one-step-ahead-of-errors-and-downtime-as-you-scale-up-your-business-lmm</link>
      <guid>https://forem.com/finnauto/how-to-stay-one-step-ahead-of-errors-and-downtime-as-you-scale-up-your-business-lmm</guid>
      <description>&lt;p&gt;Hey, so you managed to scale your business from an early-stage startup to a fast-growing scale-up. This means your tech has grown a lot since. With an ever-growing system, how do you keep an eye on everything and make sure that it is all running and customers are not facing any downtimes or errors?&lt;/p&gt;

&lt;p&gt;Well, we went through the same phase at FINN, growing from a 30 person startup in 2020 to 350+ people in 2022 and expanding to the US as well. This article presents some of my key learnings as to how to stay ahead of errors and downtimes.&lt;br&gt;
The holy trinity when it comes to minimising downtimes and errors is &lt;strong&gt;logging&lt;/strong&gt;, &lt;strong&gt;monitoring&lt;/strong&gt; and &lt;strong&gt;alerting&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Logging
&lt;/h2&gt;

&lt;p&gt;Simply speaking, logging is the act of keeping logs. Logs are entries of "events" happening in a system, for example: when did your system start, what's the hourly CPU utilisation, which user has logged in to the system, what requests were made to your API server, etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why should you log?
&lt;/h3&gt;

&lt;p&gt;Why do we need logging? The answer is: &lt;strong&gt;visibility&lt;/strong&gt;. We want to know what's going on in our system and we want our system to provide that information easily, rather than cracking our heads and making blind guesses as to what might have been the issue. To ensure this, it is our responsibility to make sure that we add proper log entries.&lt;/p&gt;

&lt;p&gt;Logs can also be processed and aggregated to get metrics like requests per hour, response time, as well as interesting business insights, such as how many orders were created in a day or an hour.&lt;/p&gt;
&lt;h3&gt;
  
  
  What should you log?
&lt;/h3&gt;

&lt;p&gt;The key here is consistency. You should have a team-wide/organisation-wide agreement on what to log and ensure that it is adhered to when it comes to code. At FINN we have agree to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timestamp (time) - so we know when it happened&lt;/li&gt;
&lt;li&gt;Log level (level) - so we know what it's meant to express (error, warning, etc)&lt;/li&gt;
&lt;li&gt;Info about source (scope) - so we can find it in the source (name of the filename)&lt;/li&gt;
&lt;li&gt;Context - so we can investigate issues (e.g. the order ID)&lt;/li&gt;
&lt;li&gt;Message that tells us what happened in English (message) - so that we can read the logs. This is the usual log message.&lt;/li&gt;
&lt;li&gt;The version of the running service (v) - so that we can tell which version of our software logged the message and helps us debug against that specific version.&lt;/li&gt;
&lt;li&gt;Who is performing the action (actor) - This is important for auditing and traceability purposes. We can easily identify who asked our systems to perform a certain action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is also very important to make sure that any sensitive information is not logged, for example: credentials, Personally Identifiable Information (PII) such as names, email, phone numbers, social security number and so on. You can instead log something such as the ID which your system uses to identify a person or order. If you really need to log some of this information, use a hash so you can check for equality without logging it.&lt;/p&gt;

&lt;p&gt;Another thing to keep in mind is to log only what you need. Logging too much will create noise and increase costs as you will need more log storage.&lt;/p&gt;
&lt;h3&gt;
  
  
  How should you log?
&lt;/h3&gt;

&lt;p&gt;How you log your data is also very crucial. For example, if you log everything in plain text, it will be very difficult to process and make meaning out of it. To make lives easier, always log in a format that can be parsed, such as JSON or XML. We chose JSON at our company because most logging libraries support it.&lt;/p&gt;

&lt;p&gt;You must take advantage of using correct log levels. There are different levels of logs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;error: Error logs are usually from unrecoverable errors. Things went wrong when we weren't expecting it. Some process failed and the system could not perform what it started, for example, if you wanted to save a file, but the write to your storage failed.&lt;/li&gt;
&lt;li&gt;warning: A warning indicates something went wrong, but the system survived and managed to complete the process it started. For example, if your system failed to send an email to the customer after order creation.&lt;/li&gt;
&lt;li&gt;info: This level of logging is used to keep track of informational metrics like a successful completion of a request, response times, etc.&lt;/li&gt;
&lt;li&gt;debug: Debug logs are used for logging things that can help you debug your system when things go wrong. It's a good practice to use debug logs to keep a track of your execution. You can log data every time you complete a step, for example when a user is authenticated, a user's profile is verified, a user's requested item is available, an order created successfully, an email sent to user.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Implementing what we learnt
&lt;/h2&gt;

&lt;p&gt;Theories without examples and illustrations are boring.&lt;/p&gt;

&lt;p&gt;I'll present our code in TypeScript to provide you with an example on how we implemented things, but it can be easily implemented in any other language as long as you stick to the principles :)&lt;/p&gt;

&lt;p&gt;We used &lt;a href="https://github.com/winstonjs/winston" rel="noopener noreferrer"&gt;Winston&lt;/a&gt; as the logging library. We also implemented our own class on top of Winston logger to enforce our conventions.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Monitoring
&lt;/h2&gt;

&lt;p&gt;Monitoring is keeping an eye on your systems, to see if everything is doing fine. The key to good monitoring is knowing what to monitor. Imagine monitoring a palace: you can’t put security cameras just about anywhere. It will be too much to handle and will distract you from keeping an eye on the main stuff. Similarly in software, you have to know which parts matter the most: for example, the checkout process is very important for an e-commerce company.&lt;/p&gt;

&lt;p&gt;Once you have identified the crucial parts, there are multiple ways to monitor them: health checks, end-to-end (E2E) tests and log-processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Health Checks
&lt;/h3&gt;

&lt;p&gt;Health checks are the starting steps towards monitoring. A simple health check would be just checking if you can connect to your system from the outside world. During the execution of the health check, your system should try connecting to its dependencies, such as a database and report if every critical dependency is available and working. If not, then it should fail and you get to know that your system is having a failure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqayy1bnwlj1s8yum64lp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqayy1bnwlj1s8yum64lp.png" alt="At FINN we use Checkly for health checks and general monitoring"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  End-to-end tests
&lt;/h3&gt;

&lt;p&gt;Health checks are limited to testing one part of a system at a time, but fail to tell you if the whole system, comprised of multiple dependent components, works as a whole. Fixing that would be the end-to-end tests. They mock a human using the system as a whole, such as going through the checkout process to order a car. This tests everything, from the input components on the website, to the backend APIs handling user requests, to the storage that stores the order data. If any test fails, we know that the real user must be facing the same issues as well, and jump into action.&lt;/p&gt;

&lt;p&gt;At FINN we use &lt;a href="https://checklyhq.com" rel="noopener noreferrer"&gt;Checkly&lt;/a&gt; once again to run our scheduled E2E tests. Some teams also use a combination of &lt;a href="https://www.make.com/en" rel="noopener noreferrer"&gt;Make&lt;/a&gt; and &lt;a href="https://apify.com/" rel="noopener noreferrer"&gt;Apify&lt;/a&gt; to run scheduled E2E tests on smaller projects.&lt;/p&gt;

&lt;p&gt;One thing I love the most about Checkly is that it allows you to write &lt;strong&gt;Monitoring as Code&lt;/strong&gt; together with Terraform. Article linked at the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Processing logs
&lt;/h3&gt;

&lt;p&gt;The previous two methods give you overall monitoring and monitoring on critical parts of the system, but not system-wide monitoring. This is where your logs come in place! If you logged errors, warnings and other information, you can process these logs and create beautiful dashboards to keep track of your systems, such as how many errors were logged per hour, how many warnings were logged in a day, number of requests served successfully, and so on.&lt;/p&gt;

&lt;p&gt;If you’re using the &lt;a href="https://www.serverless.com/framework" rel="noopener noreferrer"&gt;Serverless framework&lt;/a&gt;, using the &lt;a href="https://www.serverless.com/dashboard" rel="noopener noreferrer"&gt;Serverless Dashboard&lt;/a&gt; together with it makes things easier and provides you with ample monitoring to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqr01hi8kov156nuvvzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqr01hi8kov156nuvvzj.png" alt="One of our dashboards using Serverless Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to go pro, you can always use the mighty AWS CloudWatch and create your own dashboards. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5cs7dw4ba73ckn07hdf.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5cs7dw4ba73ckn07hdf.jpeg" alt="AWS CloudWatch Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS CloudWatch also comes with powerful querying capabilities. To use these, head over to your CloudWatch console &amp;gt; Log Groups &amp;gt; Select your resource &amp;gt; Search Log Group.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;CloudWatch is much too powerful to be described completely here. Please read AWS’ documentation on &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html" rel="noopener noreferrer"&gt;Pattern and Filter syntax&lt;/a&gt; to know more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alerting
&lt;/h3&gt;

&lt;p&gt;Alerting exists so that you get informed about errors (and maybe warnings) as soon as they happen. Alerting basically is some automation that keeps an eye on your monitored metrics (such as 5xx errors, requests per time, 4xx errors, etc) and performs some action as soon as those metrics cross a pre-defined threshold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwm18p78r3olueurby4ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwm18p78r3olueurby4ck.png" alt="Basic alerting setp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of the teams at FINN have different alerting setups, the one pictured above is one of them. For non-critical incidents, posting on Slack is enough so that the team knows about it, and can solve the issue at their own pace. For critical money-making processes, however, we use Opsgenie, which has call escalation policies in places to ensure that critical incidents are responded to within a certain amount of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;From an end-user’s perspective, one could say that logging, monitoring and alerting does not add much value, because they are not tangible features that the user can see/use. But oh boy they are so important in maintaining good user experience. Imagine how bad it would look if your customers have to call and notify you that a feature is not working.&lt;/p&gt;

&lt;p&gt;No system is 100% error-free. Rather than trying to predict all the things that can go wrong (which I think becomes a waste of time after some point) and coming up with counter-measures, a better approach IMO is to embrace the errors, be ready and have systems in place to notify you as soon as they happen.&lt;/p&gt;

&lt;p&gt;Please add your thoughts/opinions in the comments below. Would love to know how you are tackling this in your team/organisation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let’s Connect!
&lt;/h2&gt;

&lt;p&gt;If you liked this article, giving it a clap and sharing it with others would help a lot!&lt;/p&gt;

&lt;p&gt;If you would like to read more on topics such as this, including software engineering, productivity, etc, consider following me! Much appreciated.&lt;/p&gt;

&lt;p&gt;Connect with me on &lt;a href="https://www.linkedin.com/in/ishtiaquezafar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, or on &lt;a href="https://twitter.com/ZafarIshtiaque" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, I’m always happy to talk about tech, architecture and software design.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>scaleup</category>
      <category>logging</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>No-code isn’t scalable. Our learnings at FINN going from 1000 toward 100,000 car subscriptions</title>
      <dc:creator>Md. Ishtiaque Zafar</dc:creator>
      <pubDate>Tue, 19 Jul 2022 06:37:55 +0000</pubDate>
      <link>https://forem.com/finnauto/no-code-isnt-scalable-our-learnings-at-finn-going-from-1000-toward-100000-car-subscriptions-50l0</link>
      <guid>https://forem.com/finnauto/no-code-isnt-scalable-our-learnings-at-finn-going-from-1000-toward-100000-car-subscriptions-50l0</guid>
      <description>&lt;p&gt;At FINN, we grew from 0 to 20,000 car subscriptions, expanded to the US, all in just two years. Those statistics bring one word to mind: speed. We were fast, and how we did so is no secret either. If you want to know, read it here:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/@ishtiaque/how-a-german-start-up-achieved-4-mn-arr-in-one-year-89fe123e0079" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oko1i9t4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2A-D1L9KYJDj8SD7sg3NeYiQ.png" alt="Ishtiaque Zafar"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/@ishtiaque/how-a-german-start-up-achieved-4-mn-arr-in-one-year-89fe123e0079" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How A German Start-up Achieved 4 Mn € ARR In One Year | by Ishtiaque Zafar | Medium&lt;/h2&gt;
      &lt;h3&gt;Ishtiaque Zafar ・ &lt;time&gt;Apr 9, 2022&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hnDHPsJs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/medium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;All that speed came with certain costs. The tech relied heavily on no/low code tools like Airtable, Make (Integromat) and Retool, to name a few. We built a lot of microservices, automation workflows which enabled us to automate a lot of processes revolving around e-commerce and car subscriptions.&lt;/p&gt;

&lt;p&gt;Early 2021, we had our 1000th car subscription and things weren’t slowing down. Around mid-2021 we were selling 70 car subscriptions daily: our highest record being 242 cars in a day! Imagine that! By end of 2021 we had crossed 10K subscriptions! Growth-wise it was looking great, but the tech was already at its peak and showing signs of struggle.&lt;/p&gt;

&lt;p&gt;These two years of rapid prototyping and experimenting helped us learn what works well and what doesn’t, but the thing with prototypes is that they are not reliable, they break often and do not scale well.&lt;/p&gt;

&lt;p&gt;Our situation back then looked something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database (Airtable) limits&lt;/li&gt;
&lt;li&gt;Synchronisation issues&lt;/li&gt;
&lt;li&gt;Overuse of no-code tools like Make for critical business purposes&lt;/li&gt;
&lt;li&gt;Extreme coupling at data level&lt;/li&gt;
&lt;li&gt;Lack of ownership of the data model&lt;/li&gt;
&lt;li&gt;Lack of access and change control process&lt;/li&gt;
&lt;li&gt;Difficult testing process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As with all prototypes, there comes a certain time at which we realise its not working for us anymore and we start making finer products, inspired by these prototypes and the learnings. The later half of 2021 indicated that FINN had outgrown its low-code prototypes and needed something better.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GrP3Ix8x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9mc1htkk4j70f715x6o.png" alt="No-code vs pro-code over time" width="880" height="487"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Image Credits - &lt;a href="https://jasonmorrissc.github.io/post/2022-02-24_no-code/"&gt;https://jasonmorrissc.github.io/post/2022-02-24_no-code/&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Mitigating database failures
&lt;/h2&gt;

&lt;p&gt;Airtable was our database of choice in the initial days. Reason: Ease of use, easy schema changes, quick rollbacks and snapshot recovery. We chose Airtable because everyone (and not just engineers) could work with it. Soon enough we had a database with more than 40 tables and the “cars” table having nearly 400 fields! (Highly inefficient, we know.) To add to that, we had dozens of automated workflow reading and changing that data and soon our database gave up. Airtable comes with a limit of 5 requests per second per base. We were constantly hitting that target and started having more than 100 timeouts per day.&lt;/p&gt;

&lt;p&gt;We quickly set up a squad in action. This squad was called “No Time to Timeout”-squad, based on the recently released James Bond movie “No Time to Die”, with one goal: reduce daily Airtable timeouts to 0. The solution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify data that are loosely coupled and move them into separate bases, so that they can be managed independently&lt;/li&gt;
&lt;li&gt;Create read replicas for data that is used company-wide, e.g.: cars and subscription related data&lt;/li&gt;
&lt;li&gt;Identify read-heavy processes and update them to read from read replicas (this introduces a little staleness in data, but will do for now)&lt;/li&gt;
&lt;li&gt;Identify write heavy processes. For this we had to implement solutions case by case. For example, for car in-fleeting we implemented a diffing function which compares the recent changes sent by car manufacturers with the last changes and only updates the cars whose data has changed. For others, we batch the write operations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This reduced the timeouts to zero, but this was only our first step towards having a stable system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining Trust in Our Data
&lt;/h2&gt;

&lt;p&gt;We started having sync issues. Multiple sources of data, combined with lack of ownership of the data and no change control process, introduced a lot of data quality issues. Too many people changing the data directly, and partial updates to data required for certain processes made everything worse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ownership
&lt;/h3&gt;

&lt;p&gt;This was the time to promote ownership. Teams were given ownership of certain data sets, e.g. the User Acquisition team owns the leads, Operations owns the cars and subscription management, Finance owns the monetary related data, and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Access control
&lt;/h3&gt;

&lt;p&gt;Controlling read and write access to data was tackled by cutting direct database access wherever possible and instead exposing data via micro-services written by the data-owning teams. These APIs were not generic CRUD APIs allowing you to do anything, but rather intent-driven APIs which only exposed a certain part of the dataset, depending on what you needed to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  State machines
&lt;/h3&gt;

&lt;p&gt;We started defining state machines for our critical entities like Car and Subscription. We had to define “What” data can be changed, “When”, and “Under what conditions”. The plan was to increase data consistency by making it impossible to change data in a way that would lead to conflicts. For example, marking a subscription as active would require to first check with the Car management and deliveries team if they have actually handed over the car. They would need to check with the Finance team if the deposit had been paid. Here’s one of our drafts for the Subscription state machine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uj5HayTe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nh3f9gddexesp77x7ah0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uj5HayTe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nh3f9gddexesp77x7ah0.png" alt="subscription state machine" width="880" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Going pro-code with project Green Dragon 🐉
&lt;/h2&gt;

&lt;p&gt;The issues mentioned above made it crystal clear that we would not be able to scale. Moreover, soon we would have to expand into the US and things would only get more intense. We needed a system that was reliable as we simply could not afford to be in fire-fighting mode all the time. Where would be the time for new features, if all engineering effort was spent on maintaining the current system?&lt;/p&gt;

&lt;p&gt;We decided to build new systems based on time-tested technologies and move away from the no-code/low-code solutions we had. We laid down some basic Engineering Principles to be followed. This was very challenging, because we had to keep the company and the business running till the new systems could take over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reduce risk to minimum
&lt;/h2&gt;

&lt;p&gt;In my colleague Andrea’s words: Migrations are never easy and they hardly go as smoothly as we hoped. Our goal was to reduce the risk to minimum so that we could act quickly to respond to problems that might arise.&lt;/p&gt;

&lt;p&gt;We came up with a strategy “Think 10x”. The idea was to start small, with just 10 cars targeted to be sold, and then scale 10 times in each phase. 10 cars → 100 cars → 1,000 … 100,000 cars. This ambitious project was called the “Green Dragon”.&lt;/p&gt;

&lt;p&gt;The first phase, called “MVP 10”, was to focus on one part of the entire car subscription process and to go live with just 10 cars up for subscription from the new system on our website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enforce good engineering practices
&lt;/h2&gt;

&lt;p&gt;Good systems are built on good principles. They guide us and help us make decisions when we have doubts. At FINN, we needed good principles for our new phase, the one where we double down on tech and make our critical systems better. Here the engineering principles we laid down at FINN:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep it simple: we want to solve today’s problem in a simple way with an eye looking at tomorrow, rather than solving tomorrow’s problem today&lt;/li&gt;
&lt;li&gt;Embrace errors: We operate in a legacy environment where failures are common. We don’t want to fight errors, we want to embrace them and design with failure in mind&lt;/li&gt;
&lt;li&gt;Make it visible: Our services must talk to us, tell us what is happening and show us how well they are doing. We don’t want to find things out, we want to be told&lt;/li&gt;
&lt;li&gt;Internalise complexity: We cannot change how our partners work, but we can change how easy we make it for them to work with us&lt;/li&gt;
&lt;li&gt;Customer first: Our customers rely on us to give them the best possible experience, but they also trust us to manage their data and information&lt;/li&gt;
&lt;li&gt;Data is always accessible: we never want to block people from reading our data and we should always provide a way for them to do it without any work&lt;/li&gt;
&lt;li&gt;Clear is better than clever: We strive for readable code that is easy to understand and change. Our goal is not to write the least amount of code, but the clearest. Magic is not our friend here
Once again, credits for laying down these principles goes to &lt;a href="https://www.linkedin.com/in/andreaperizzato/"&gt;Andrea&lt;/a&gt; :)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reducing disruption to minimum
&lt;/h2&gt;

&lt;p&gt;FINN is very pro-automation, and we didn’t want to disrupt that. Everyone at FINN knows how to work with the automation platform Make (formerly Integromat) and leverages it to automate their day to work. Since data would not be so open anymore, we needed to provide a way for our colleagues to be able to use the new system from the comfort of Make. We made custom apps on Make which enabled our colleagues to use our new core APIs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Bjtsuvt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/184crqe8is5h4a28g0ce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Bjtsuvt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/184crqe8is5h4a28g0ce.png" alt="reducing disruption via no-code bridges" width="880" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our colleagues also need custom dashboards showing different data to enable their day-to-day work, such as overseeing and managing daily deliveries, damage management, incident handling and customer care. They need parts of subscription data, car data, financial data and much more. They also need to be able to perform some actions on this data. For this, we built them dashboards using &lt;a href="https://retool.com/"&gt;Retool&lt;/a&gt;, so that they don’t need direct access to data as in the old system at FINN. This allowed us to have data validations and checks in place, and only allow data writes through our intent-driven APIs. This was such an enabler to help us keep our data consistent, while promoting easy access to data at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where are we today?
&lt;/h2&gt;

&lt;p&gt;Mitigating our issues to get the current system working and give us some breathing room to focus on developing the new system surely feels something like this famous meme:&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://gfycat.com/blushingbeautifulaustraliansilkyterrier" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--VkBsYNX---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thumbs.gfycat.com/BlushingBeautifulAustraliansilkyterrier-size_restricted.gif" height="273" class="m-0" width="341"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://gfycat.com/blushingbeautifulaustraliansilkyterrier" rel="noopener noreferrer" class="c-link"&gt;
          Fixing A Bug In A Production GIF | Gfycat
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Watch and share Fixing A Bug In A Production GIFs on Gfycat
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--e_7jJj7z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://gfycat.com/assets/favicons/favicon-16x16.png" width="16" height="16"&gt;
        gfycat.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Thankfully, with excellent teamwork across departments and multiple mitigation squads, we were able to stabilize our current systems. We took this Green Dragon project as an opportunity to show what real tech could do in all its glory. Every one was super energetic and enthusiastic about developing systems that would support FINN for the next phase of growth! We went live on June 28th 2022 with the MVP 10 phase smoothly and sold our first “Green Dragon” car subscription on June 30th and we aren’t slowing down. Huge shout out to &lt;a href="https://www.linkedin.com/in/andreaperizzato/"&gt;Andrea Perizzato&lt;/a&gt; for leading this initiative ❤&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;We are going full flat out as we rebuild the tech that powers FINN. Watch this space for more insights about our tech and the next phases that we go live with!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;No-code is cool and fast, and got us to where we are today, much faster than our competitors, but it won’t help us get where we want to. We have entered the next phase of growth where we take what we have learnt in the last two years and make it even better, more robust and scalable. We have set good practices in place to guide us along this way and we will continue to embrace struggle till we get to 100,000 car subscriptions.&lt;/p&gt;




&lt;p&gt;If you liked this article, liking it and sharing it with others would help a lot!&lt;/p&gt;

&lt;p&gt;If you would like to read more on topic such as this, software engineering, productivity, etc, consider following me! Much appreciated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/ishtiaquezafar/"&gt;Connect with me on LinkedIn&lt;/a&gt;, I’m always happy to talk about tech, architecture and software design.&lt;/p&gt;

&lt;p&gt;Lastly, FINN is hiring! If you want to be a part of this crazy growth and work alongside super awesome colleagues, consider having a look at our &lt;a href="https://finn.auto/careers"&gt;careers page&lt;/a&gt; or simply reaching out to me :) FINN is very diverse and inclusive, also consider having a look at our &lt;a href="https://jobs.lever.co/finn.auto/d9e72ce9-eb12-45e4-b049-1e55f24adc52?lever-origin=applied&amp;amp;lever-source%5B%5D=Blog%20Article"&gt;Women in Tech&lt;/a&gt; programme ❤&lt;/p&gt;

</description>
      <category>startup</category>
      <category>scalabilty</category>
      <category>nocode</category>
    </item>
    <item>
      <title>Why I don’t like API frameworks together with Serverless</title>
      <dc:creator>Md. Ishtiaque Zafar</dc:creator>
      <pubDate>Mon, 02 May 2022 10:57:13 +0000</pubDate>
      <link>https://forem.com/finnauto/why-i-dont-like-api-frameworks-together-with-serverless-12m5</link>
      <guid>https://forem.com/finnauto/why-i-dont-like-api-frameworks-together-with-serverless-12m5</guid>
      <description>&lt;p&gt;&lt;em&gt;This blog was originally published &lt;a href="https://medium.com/@ishtiaque/why-i-dont-like-api-frameworks-together-with-serverless-39200063b4e0" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every time when creating a new API that is meant to be serverless, I consider or have been asked to consider using an API framework together with a serverless application framework like &lt;a href="https://www.serverless.com/framework" rel="noopener noreferrer"&gt;Serverless Framework&lt;/a&gt; or &lt;a href="https://aws.amazon.com/serverless/sam/" rel="noopener noreferrer"&gt;AWS SAM&lt;/a&gt;. So far, I have found none that impress me. Here’s why:&lt;/p&gt;

&lt;h2&gt;
  
  
  They do not promote modularity
&lt;/h2&gt;

&lt;p&gt;If you have a look at frameworks like &lt;a href="https://github.com/dougmoscrop/serverless-http" rel="noopener noreferrer"&gt;serverless-http&lt;/a&gt; or &lt;a href="https://docs.nestjs.com/faq/serverless" rel="noopener noreferrer"&gt;nestjs + serverless&lt;/a&gt;, or at &lt;a href="https://pythonforundergradengineers.com/deploy-serverless-web-app-aws-lambda-zappa.html" rel="noopener noreferrer"&gt;zappa + flask&lt;/a&gt; for python lovers, all of them follow the same pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Instantiate an app&lt;/li&gt;
&lt;li&gt;Add routes and associated handler functions to the app&lt;/li&gt;
&lt;li&gt;Add middlewares for authorisation, logging, etc, in the app itself&lt;/li&gt;
&lt;li&gt;Bundle everything into a single lambda function which gets triggered with the base path &lt;code&gt;ANY /&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqx7ta3c4d2a08qab09k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqx7ta3c4d2a08qab09k.png" alt="How your deployed code would look with an API framework"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How your deployed code would look with an API framework&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You see how heavy-weight it can be. It’s like packing your monolith app into a single lambda function and executing it. Heavier code will lead to longer boot times and hence longer response time compared to the no-framework approach. Poor lambdas are not meant to be used in such a way. You might get away with small apps, but if your monolith is huge, it’s better to use some other solution like containerisation with ECS.&lt;br&gt;
A better solution, in my sense, should be something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk235cwsi9slu0erjgoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk235cwsi9slu0erjgoc.png" alt="Without any API framework"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Without any API framework&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every lambda function contains just your business logic and code needed to interact with data sources. Such lightweight, much wow, very fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not offload overhead actions elsewhere?
&lt;/h2&gt;

&lt;p&gt;An API does not just include your business logic, it needs to have some other must-have functionalities, like routing, input validation and authorisation, to name a few.&lt;/p&gt;

&lt;p&gt;Most of these API frameworks come from times before the serverless revolution, and were designed to create API services to be run on “dumb” infrastructure, dumb in the sense that they were just compute resources, not capable of anything else like routing, request authorisation, etc. Hence, everything had to be done (and written by you!) in the code.&lt;/p&gt;

&lt;p&gt;Going truly serverless means that you break your system into parts and then use readily available managed services which take care of individual responsibilities. For example, routing and input validation can be done by the API Gateway. You can have a custom lambda authoriser for authenticating all your requests. For your business logic, you can have lambda functions small enough to focus on one topic per function.&lt;br&gt;
Have a look below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0i7dvhwhqx8ml7h7ypnp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0i7dvhwhqx8ml7h7ypnp.png" alt="A better serverless system with offloaded responsibilities"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adds unnecessary learning curve
&lt;/h2&gt;

&lt;p&gt;They add an unnecessary learning curve for the team. A new engineer on the team needs to learn the new framework as well. So why introduce one more thing to learn for your team, when writing small functions is the ultimate goal.&lt;/p&gt;

&lt;p&gt;Take django for example. This framework has such a high learning curve and is somewhat opinionated. The goal of lambda functions was to enable developers to execute arbitrary functions, not entire apps, in a lightweight container-like solution. Read that again: “…functions, not entire apps, in a lightweight container-like…”. Using just the Serverless Framework or AWS SAM gives you so much flexibility and speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downsides
&lt;/h2&gt;

&lt;p&gt;One downside I have noticed working with a barebones framework is that the code is non-standard. Each project uses the Serverless framework, but the code structure is different in each one of them. Here are three different structures I’ve worked with recently:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrcokstj40uv3v06rpoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrcokstj40uv3v06rpoc.png" alt="Different folder structures"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see clearly how vastly it varies, mostly depending on the team and it might add to the onboarding time. As said earlier, this is a tradeoff against learning an API framework and the heaviness that comes with it. This can be easily tackled by following the same core principles which these API frameworks use.&lt;/p&gt;

&lt;p&gt;Another downside of hyper-granularity is that you end up having many functions that share significant portion of the same code, and now you have that many more cold-starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In tech, no solution is the perfect solution, every single one of them comes with tradeoffs, so it’s up to you to decide which ones you can live with.&lt;br&gt;
Got different opinions? I would love to discuss them. Drop them in the comments below!&lt;/p&gt;




&lt;p&gt;If you liked this article, sharing it in your network would help a lot!&lt;/p&gt;

&lt;p&gt;Connect with me on &lt;a href="https://www.linkedin.com/in/ishtiaquezafar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://twitter.com/zafarishtiaque" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://medium.com/@ishtiaque" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>api</category>
    </item>
  </channel>
</rss>
