<?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: Julie Hourcade</title>
    <description>The latest articles on Forem by Julie Hourcade (@louhdetech).</description>
    <link>https://forem.com/louhdetech</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%2F4037%2F9eb00950-4bde-4027-bc99-225ee59434d8.jpeg</url>
      <title>Forem: Julie Hourcade</title>
      <link>https://forem.com/louhdetech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/louhdetech"/>
    <language>en</language>
    <item>
      <title>Level up your secrets management in Kubernetes using AWS Secret Manager and Helm</title>
      <dc:creator>Julie Hourcade</dc:creator>
      <pubDate>Mon, 26 Dec 2022 09:04:11 +0000</pubDate>
      <link>https://forem.com/formance/level-up-your-secrets-management-in-kubernetes-using-aws-secret-manager-and-helm-c80</link>
      <guid>https://forem.com/formance/level-up-your-secrets-management-in-kubernetes-using-aws-secret-manager-and-helm-c80</guid>
      <description>&lt;p&gt;Engineers' biggest struggle when writing Kubernetes resources is to keep all secrets secure. To be honest, the secrets k8s resource is not secured at all because base64 is not encryption!&lt;/p&gt;

&lt;p&gt;Required skills: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding basic concepts about Kubernetes&lt;/li&gt;
&lt;li&gt;Cloud providers resources knowledge&lt;/li&gt;
&lt;li&gt;Helm &lt;strong&gt;v3&lt;/strong&gt; installed on a Kubernetes cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding Helm
&lt;/h2&gt;

&lt;p&gt;For this article and for Formance infrastructure we chose to use Helm as a templating system for our k8s resources. This software is commonly known as the package manager for Kubernetes but they also provide a good system for deploying many versions of the same Charts, like for production and staging environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialize the application
&lt;/h3&gt;

&lt;p&gt;First, we have to create a new application using the Helm CLI. You could find how to install it here: &lt;a href="https://helm.sh/docs/intro/quickstart/" rel="noopener noreferrer"&gt;https://helm.sh/docs/intro/quickstart/&lt;/a&gt;. Once all is installed correctly, you could run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm create &lt;span class="s2"&gt;"&amp;lt;your_application_name&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The directory Helm creates should look like this ⬇️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fpot60aquqs1bviodsjo7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fpot60aquqs1bviodsjo7.png" alt="Tree of the directory" width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we’re going to stay basic and remove some templates to keep it simple. We’re only keeping: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The deployment template&lt;/li&gt;
&lt;li&gt;The service template&lt;/li&gt;
&lt;li&gt;The service account template&lt;/li&gt;
&lt;li&gt;The helpers, Notes, and Tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we will create a file named &lt;code&gt;secret.yaml&lt;/code&gt; for the template of our SecretProvider object. &lt;/p&gt;

&lt;p&gt;If you’re not familiar with the Helm templating language, I recommend you take a look at the documentation: &lt;a href="https://helm.sh/docs/chart_template_guide/" rel="noopener noreferrer"&gt;https://helm.sh/docs/chart_template_guide/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The secret provider object
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Concept
&lt;/h3&gt;

&lt;h4&gt;
  
  
  What are CSI Drivers?
&lt;/h4&gt;

&lt;p&gt;To perform what we want, we’re going to use a Kubernetes resource named SecretProviderClass from the API &lt;code&gt;secrets-store.csi.x-k8s.io/v1alpha1&lt;/code&gt;.  The secret store is provided by the Kubernetes Container Storage Interface which here helps us to connect basic resources like volumes or secrets to cloud providers' services. &lt;/p&gt;

&lt;p&gt;The main problem of Secrets resources on Kubernetes is the lack of security and if I want to share some private values as database passwords to my application deployment, I need more than just a base64 encryption.&lt;/p&gt;

&lt;p&gt;Here at Formance we use Amazon Web Services as cloud provider so I will use the service AWS Secret Manager (docs: &lt;a href="https://docs.aws.amazon.com/secretsmanager/?id=docs_gateway" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/secretsmanager/?id=docs_gateway&lt;/a&gt;). When we have created our Relational Database Service with MariaDB or PostgreSQL or whatever, using InfraAsCode tools Terraform, we have automatically created a Secret with the database login information. The problem is to retrieve those values directly on my application container automatically. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Simplified overview of the workflow&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.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%2Fuaowdoz6zu6vzohti99t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fuaowdoz6zu6vzohti99t.png" alt="Simplified overview of the workflow" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Installing the Secret Store CSI driver
&lt;/h4&gt;

&lt;p&gt;That’s here where Kubernetes CSI enters in action ! It will create an interface between our Secret object on AWS and our application deployment. First of all, we have to install the Secret Store CSI driver using helm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add secrets-store-CSI-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm &lt;span class="nb"&gt;install &lt;/span&gt;csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver &lt;span class="nt"&gt;--namespace&lt;/span&gt; kube-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could find an alternative installation here: &lt;a href="https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html" rel="noopener noreferrer"&gt;https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will install things like the operator, and service account with the right RBAC permissions and most important, it will declare the Custom Resources Definition of the SecretProviderClass. Without this, the Kubernetes Scheduler will not understand the API version and the object kind. &lt;/p&gt;

&lt;p&gt;Secret store CSI driver also supports GCP, Azure, and Vault secrets providers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deep dive into the secret template
&lt;/h3&gt;

&lt;p&gt;The requirement is to make a template where we could inject some specific values like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The name obviously&lt;/li&gt;
&lt;li&gt;The secret provider (note that this example is only tested on AWS)&lt;/li&gt;
&lt;li&gt;And the secrets to retrieve using the secret name or in AWS its Amazon Resource Name (ARN)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keep in mind that this example is a simple template with multiple secrets but you personalize it as you wish. You can find various &lt;/p&gt;

&lt;p&gt;Let’s take a look at the template and its values:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fule95nfdlewdrs9octzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fule95nfdlewdrs9octzt.png" alt="secret yaml" width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9sfnn04spy7d5674sbdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9sfnn04spy7d5674sbdk.png" alt="extract of values.yaml" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you create all templates, all you have to do is to apply the command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;helm install &amp;lt;application name&amp;gt; .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And you're all done!&lt;/p&gt;

&lt;p&gt;Image credits: &lt;a href="https://www.midjourney.com/home/" rel="noopener noreferrer"&gt;Midjourney&lt;/a&gt; &lt;/p&gt;

</description>
      <category>security</category>
      <category>cloud</category>
      <category>aws</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building an Uber Eats Clone</title>
      <dc:creator>Julie Hourcade</dc:creator>
      <pubDate>Thu, 02 Jun 2022 11:43:29 +0000</pubDate>
      <link>https://forem.com/formance/building-an-uber-eats-clone-38j8</link>
      <guid>https://forem.com/formance/building-an-uber-eats-clone-38j8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Initialy published on &lt;a href="https://32b6.com/articles/uber-eats-clone-1" rel="noopener noreferrer"&gt;https://32b6.com&lt;/a&gt; by Clément Salaün&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Templating money flows with Numscript
&lt;/h3&gt;

&lt;p&gt;We explore in this article the money problem behind creating a food delivery platform, focusing on building the core money movements using the Formance &lt;a href="https://github.com/numary/ledger" rel="noopener noreferrer"&gt;ledger&lt;/a&gt; and Numscript as the foundation of our real-time accounting system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three-sided Platform
&lt;/h2&gt;

&lt;p&gt;From a money flow perspective, Eats is a classic &lt;a href="https://a16z.com/2020/02/18/marketplace-glossary/" rel="noopener noreferrer"&gt;n-sided marketplace&lt;/a&gt; (where N=3). It is a machine that reads your credit card details, materializes a pizza on your porch and a platform, facilitates a transaction between three parties: the customer, the restaurant and the rider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fl5z1ky1c840l5txnlfgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fl5z1ky1c840l5txnlfgb.png" alt="graph" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some payments services providers give us constructs to route an incoming payment, to a certain extent. Stripe Connect for example has &lt;a href="https://stripe.com/docs/connect/destination-charges" rel="noopener noreferrer"&gt;destination charges&lt;/a&gt;, which give you the ability to provide the end destination account and your commission amount at payment. This is not super helpful for our food delivery app given that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have more than 1 destination (the restaurant and rider)&lt;/li&gt;
&lt;li&gt;We don’t know, at payment time, who is going to be the rider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To these issues, Stripe answers with another turnkey solution called &lt;a href="https://stripe.com/docs/connect/charges-transfers" rel="noopener noreferrer"&gt;separate charges and transfers&lt;/a&gt;. It basically solves all our concerns, at one cost: we are now responsible for tracking what is owed to whom. Ledger systems are a good candidate for achieving this, as we’ll attempt to demonstrate in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Templating our flow
&lt;/h2&gt;

&lt;p&gt;Not bothering with unique values (for now), let’s start to encode our money flow in Numscript using hardcoded values. If you want to follow along, Numscript files can be executed against a locally running Formance ledger directly from the cli:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;numary exec "eats-clone-demo" example.num
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The payment
&lt;/h3&gt;

&lt;p&gt;Using an intermediate payment ledger account helps us divide our flow into multiple sub-problems. Prior to splitting, our first mission is to properly track how much we collected from our customer. Let’s start with a simple case by assuming we managed to collect $59 through Stripe:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhocgnks6nwm33q5xe8g7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhocgnks6nwm33q5xe8g7.png" alt="code" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use here the &lt;code&gt;@world&lt;/code&gt; account to introduce money into our ledger (as per the &lt;a href="https://docs.formance.com/docs/creating-money" rel="noopener noreferrer"&gt;spec&lt;/a&gt;). If its USD balance was zero before this transaction, it will now be negative 59. We can note as well that we use here &lt;code&gt;USD/2&lt;/code&gt; instead of &lt;code&gt;USD&lt;/code&gt;, which is basically a &lt;a href="https://docs.formance.com/oss/ledger/reference/unambiguous-monetary-notation" rel="noopener noreferrer"&gt;notation&lt;/a&gt; for USD scaled to 10^-2 i.e. USD cents.&lt;/p&gt;

&lt;p&gt;We conclude the payment by flushing the funds we collected to an order account, which will receive the funds without ever bothering about their origin:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F15elg98dgraqcg1l96ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F15elg98dgraqcg1l96ao.png" alt="code" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Philosophically, we consider stripe as an external ledger that now owes money to our local ledger. In the real world, money hasn’t moved but we penciled in that this money is now dedicated to this order.&lt;/p&gt;

&lt;h3&gt;
  
  
  The split
&lt;/h3&gt;

&lt;p&gt;Moving further in the flow, we now task ourselves with splitting the customer payment to the rider, restaurant and our platform. This splitting script is typically where we would encode our platform commission logic. We make the decision here of taking a 15% cut on each amount we pay the restaurant, leaving the delivery fee entirely to the rider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkuczqiqw5zeyzugb1v5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkuczqiqw5zeyzugb1v5z.png" alt="code" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The payout
&lt;/h3&gt;

&lt;p&gt;We now have riders and and restaurants accounts in our ledger with a positive balance, whose purpose is to eventually be paid out to their owners’ banks.On the rider and restaurant views of our app, we’ll typically display these balances as “available for payout” funds.&lt;/p&gt;

&lt;p&gt;Sticking to Stripe, one way to achive the processing of these balances can be to move the balance from a &lt;code&gt;restaurants:001&lt;/code&gt; account to a &lt;code&gt;restaurants:001:payouts:001&lt;/code&gt; account, initiating a &lt;a href="https://stripe.com/docs/api/transfers/create" rel="noopener noreferrer"&gt;transfer&lt;/a&gt; and a &lt;a href="https://stripe.com/docs/api/payouts/create" rel="noopener noreferrer"&gt;payout&lt;/a&gt; on Stripe of that amount, and eventually moving the balance from &lt;code&gt;restaurants:001:payouts:001&lt;/code&gt; back to &lt;code&gt;world&lt;/code&gt; once we successfully processed the payout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating our flow
&lt;/h2&gt;

&lt;p&gt;Using hardcoded values in Numscript will only get us so far. As we start to execute our templates automatically from a backend, we will typically start to use variables, passing them along with the script on the &lt;a href="https://docs.formance.com/oss/ledger/reference/api#operation/runScript" rel="noopener noreferrer"&gt;/script&lt;/a&gt; endpoint&lt;/p&gt;

&lt;h3&gt;
  
  
  Using execution variables
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcdqwauh3ae2utt32hihl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcdqwauh3ae2utt32hihl.png" alt="code" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a commission from metadata
&lt;/h3&gt;

&lt;p&gt;As we iterate with our platform economics, we’ll likely end up with different commission rates per restaurant. We can inject this commission as a variable as well, fetching it the example below from the restaurant account metadata:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhcq1r39at41vop5otyac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhcq1r39at41vop5otyac.png" alt="code" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  More complexity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Coupons
&lt;/h3&gt;

&lt;p&gt;Inundating the buy side with generous coupons is a common strategy to break the chicken and egg problem platforms face. If you’re really going for an Eats clone, you may subsidize the buy side so much that you’ll end up spending more for a purchase in discount than the commission you’ll get out of it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxahyuje82ty02i7knxca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxahyuje82ty02i7knxca.png" alt="graph" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the grand scheme of the above example, as a platform, we are $8 short overall. If this was the only payment flow to ever happen on our Stripe account, we wouldn’t be able to cover payouts to the rider and restaurant.&lt;/p&gt;

&lt;p&gt;As we rinse and repeat this process for thousands of sales, it becomes critical to properly track these marketing losses to avoid putting ourselves at risk of ever defaulting payouts.&lt;/p&gt;

&lt;p&gt;Numscript comes with multi-sources transactions which we can use to model our marketing expense. Let’s first credit $15k to a coupon account for a specific campaign:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fn07n2xmnt4g51npihlvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fn07n2xmnt4g51npihlvx.png" alt="code" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then in script executing at payment time, we’ll use this coupons as a source of marketing funds, from which we’ll draw up to $19.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fswon75hmd7nc5d42kqzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fswon75hmd7nc5d42kqzv.png" alt="code" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Refunds at loss
&lt;/h3&gt;

&lt;p&gt;So, the food arrived colder than it left the freezer at the restaurant. Customer files a ticket and you can’t know for sure wether the weather, rider, or restaurant is at fault here. As a platform you may decide to eat the loss, issuing a partial refund to your customer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fu6ac51fw9sr31s7hkcti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fu6ac51fw9sr31s7hkcti.png" alt="graph" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Properly registering this loss as a money movement in our ledger will, in addition to keeping the books in check, once again help us prevent defaulting risk as we’ll be able to create routine processes of topping-up your Stripe platform account to cover for losses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reconciliation
&lt;/h2&gt;

&lt;p&gt;The internal flow we defined in blue sits between &lt;em&gt;input&lt;/em&gt; and &lt;em&gt;output&lt;/em&gt;. It tracks what is owed to whom, and only makes sense if it eventually supports actual money movements in the real world, which we achieve through payments processors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fheoekexgjyabydf52in3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fheoekexgjyabydf52in3.png" alt="graph" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recon is a complex payments 101 problem. We want to make sure that assumptions we make in our system, e.g. that we received $59 from our customer, hold true in the external systems we use over time. As an example, your customer may charge back their payment after a few weeks, breaking your reconciliation. Ideally, every payment on your provider should be linked to an internal ledger transaction. In a further article, we’ll cover techniques and scripts to continuously reconcile our flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes on legal design and compliance
&lt;/h2&gt;

&lt;p&gt;We mentioned defaulting risk a few times in this piece. I’ve heard objections to this concern, usually quoting perpetual growth combined with positive cash float as a mechanism to make up for platform losses and marketing expenses. This can only be true if properly measured with a ledgering strategy and to the surprise of no one, auditors are not particularily fond of this scheme, no matter how exciting the idea of a fractional-reserve marketplace sounds on paper.&lt;/p&gt;

&lt;p&gt;In any case, your local lawyers are the best advisors on what you can and cannot do with your payments flows.&lt;/p&gt;




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

&lt;p&gt;As a platform, having a holistic view of your money flows and being able to know at any point in time what is owed to whom is critical. Using a ledger-oriented programmation model will help us achieve both reliability and visibility, as immutable transactions become the fundamental construct of state in our system.&lt;/p&gt;

</description>
      <category>payment</category>
      <category>ledger</category>
      <category>go</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Docker everywhere is not a good thing.</title>
      <dc:creator>Julie Hourcade</dc:creator>
      <pubDate>Fri, 10 May 2019 10:20:29 +0000</pubDate>
      <link>https://forem.com/louhdetech/docker-everywhere-is-not-a-good-thing-4i</link>
      <guid>https://forem.com/louhdetech/docker-everywhere-is-not-a-good-thing-4i</guid>
      <description>&lt;p&gt;Docker is a trend and everyone want to be part of this but not really in a good way. The bad side of this trend is that everything goes on container, like web app or database even GitLab to the detriment of data persistence, security and maybe performance in in certain case.&lt;/p&gt;

&lt;p&gt;One of a solution is, IMHO, to use a orchestrator like Swarm or Kubernetes with a good study of which kind of volumes all your containers need. You can also make security better with a good reverse proxy and using RBAC for Kubernetes. &lt;/p&gt;

&lt;p&gt;What is your methods to keep your data safe, to make container secure and to have good performances on your conteneurized website ?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>docker</category>
      <category>serverless</category>
      <category>devops</category>
    </item>
    <item>
      <title>Docker Best Practices, back to basics.</title>
      <dc:creator>Julie Hourcade</dc:creator>
      <pubDate>Tue, 30 Apr 2019 10:16:14 +0000</pubDate>
      <link>https://forem.com/louhdetech/docker-best-practices-back-to-basics-cg7</link>
      <guid>https://forem.com/louhdetech/docker-best-practices-back-to-basics-cg7</guid>
      <description>&lt;p&gt;You're new to Docker ? I was too. Everyone wants to build awesome projects with Docker, build some images and start containers. That's cool ! Docker is cool. But you missed a point, there are some rules to use it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rule number one ! Keep it simple and small.
&lt;/h1&gt;

&lt;p&gt;Docker images are meant to be SMALL. As small as possible.&lt;br&gt;
Docker is a conteneurisation system not a virtual machine. Don't reproduce all your GNU/Linux distribution on it.&lt;/p&gt;

&lt;p&gt;To have a lightweight image, you can first take a look to Alpine versions. Alpine is a Linux based on MUSL and BusyBox instead of basical GNU. If you want to use a Debian base image anyway, don't forget to clean apt after installing packets.&lt;/p&gt;

&lt;h1&gt;
  
  
  Choose a Official Docker image, you must.
&lt;/h1&gt;

&lt;p&gt;There is an ocean of Docker images available on Docker Hub but they are not all secured. You must choose a official image and add to it what you need. For example, don't use a PHP image made by a unknown person found on the Hub but prefer to use the php official image with the adapted tag.&lt;/p&gt;

&lt;p&gt;If you really need to use a unofficial image, take a look at the Dockerfile. Most of images provides the Dockerfile associated to the image. If the base image is based itself on an other unofficial image, search it  ! Go the deeper possible. Finally, avoid closed images with no Dockerfile provided, it could be insecure. &lt;/p&gt;

&lt;h1&gt;
  
  
  You're saying image tag ? Don't use the latest.
&lt;/h1&gt;

&lt;p&gt;When you're building a Dockerfile, everyone has already added a FROM statement with the latest tag on the image. Everyone, don't lie.&lt;br&gt;
So don't do that ! For the simple reason that the latest tag is the latest not the more stable. If the latest tag change to an upper version it could broke all your system. You should consider to choose a version no matter the base image you use.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dev environements are not the same as Prod environements.
&lt;/h1&gt;

&lt;p&gt;For a use in production, there are more rules.&lt;br&gt;
First of all, don't use docker-compose on production. Prefer using a orchestrator like Swarm or Kubernetes. If you have to use docker-compose on a project, you could switch to an orchestrator. It's not too much.&lt;/p&gt;

&lt;p&gt;Secondly, containers should be stateless. For example, don't conteneurize databases. &lt;/p&gt;

&lt;p&gt;Finally, One container, One task. A container should do only one thing like running a webserver, execute a script, run a ElasticSearch or a Redis or a RabbitMQ even a GitLab but not all together.&lt;/p&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;To conclude :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make small and simple images&lt;/li&gt;
&lt;li&gt;Use official Docker Hub images as possible&lt;/li&gt;
&lt;li&gt;Never use the latest tag&lt;/li&gt;
&lt;li&gt;Be careful on what you're doing on production&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Useful links
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/develop/dev-best-practices/"&gt;https://docs.docker.com/develop/dev-best-practices/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/"&gt;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/&lt;/a&gt;&lt;br&gt;
and all the Docker documentation &lt;/p&gt;

&lt;p&gt;Feel free to add your best practices in comments !&lt;/p&gt;

</description>
      <category>docker</category>
      <category>beginners</category>
      <category>devops</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Explain container orchestration like i'm five</title>
      <dc:creator>Julie Hourcade</dc:creator>
      <pubDate>Wed, 18 Oct 2017 15:22:02 +0000</pubDate>
      <link>https://forem.com/louhdetech/explain-container-orchestration-like-im-five-a5j</link>
      <guid>https://forem.com/louhdetech/explain-container-orchestration-like-im-five-a5j</guid>
      <description>&lt;p&gt;Hi everyone, &lt;/p&gt;

&lt;p&gt;After a little more than 3 months internship, i have to do my report. I know what is container and orchestration but i'm really bad at explain it. So explain me container orchestration like i'm five ! &lt;/p&gt;

</description>
      <category>explainlikeimfive</category>
      <category>discuss</category>
      <category>cloud</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
