<?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>DEV Community: Feras Allaou</title>
    <description>The latest articles on DEV Community by Feras Allaou (@ferasallaou).</description>
    <link>https://dev.to/ferasallaou</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F357615%2F23bbf7d0-d869-4325-acd4-643e27ec0c64.jpg</url>
      <title>DEV Community: Feras Allaou</title>
      <link>https://dev.to/ferasallaou</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ferasallaou"/>
    <language>en</language>
    <item>
      <title>You already wrote your infrastructure. It's called your NestJS/ExpressJS App!</title>
      <dc:creator>Feras Allaou</dc:creator>
      <pubDate>Sun, 02 Aug 2026 04:46:15 +0000</pubDate>
      <link>https://dev.to/ferasallaou/you-already-wrote-your-infrastructure-its-called-your-nestjsexpressjs-app-73l</link>
      <guid>https://dev.to/ferasallaou/you-already-wrote-your-infrastructure-its-called-your-nestjsexpressjs-app-73l</guid>
      <description>&lt;h2&gt;
  
  
  Adding a cron job should be one file
&lt;/h2&gt;

&lt;p&gt;Here's a thing that happens on every NestJS project I've worked on.&lt;/p&gt;

&lt;p&gt;You need a job that refreshes a cache every five minutes. In your app, that's one function. Twelve lines, tops.&lt;/p&gt;

&lt;p&gt;Then you go make it real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;code&gt;Rule&lt;/code&gt; in your CDK stack (or a &lt;code&gt;aws_cloudwatch_event_rule&lt;/code&gt; in Terraform)&lt;/li&gt;
&lt;li&gt;a second Lambda, because the API function shouldn't own it&lt;/li&gt;
&lt;li&gt;a new bundle entry so the job actually gets built&lt;/li&gt;
&lt;li&gt;an IAM policy, because it reads from the same table&lt;/li&gt;
&lt;li&gt;an env var, added in two places, because the infra repo has its own idea of config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five files, none of which are the twelve lines you actually wrote. And every one of them is a &lt;em&gt;restatement&lt;/em&gt; of a fact your code already knows.&lt;/p&gt;

&lt;p&gt;That's the part that always bothered me. The infrastructure isn't new information. It's a translation of something already sitting in your source tree and you're the translator, forever, by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two options, and what each one costs
&lt;/h2&gt;

&lt;p&gt;Broadly you pick one of these.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A platform.&lt;/strong&gt; Push, get a URL. Genuinely great until you need a queue, or your compliance person asks where the data lives, or you look at the bill and realize you're paying a markup to run in someone else's account. You don't own the infrastructure, so you can't inspect it, can't extend it, and can't leave with it.&lt;/p&gt;

&lt;p&gt;Worth calling out: some platforms in the Node space solve "deploy to your own cloud" by asking you to create a long-lived IAM user with near-admin permissions and hand it over. That's your account, technically. It's also a set of keys you don't control, sitting in someone else's database, with rights to read your secrets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure as code.&lt;/strong&gt; CDK, Terraform, Pulumi, SAM. You own everything, everything is inspectable, nothing is magic. The cost is that you now maintain a second codebase whose entire job is to describe the first one and the two drift. Not dramatically. Quietly. A route gets deleted and its rule stays. A queue gets renamed in the app and the consumer keeps polling the old one. An env var is added to &lt;code&gt;.env&lt;/code&gt; and not to the stack, and you find out in production.&lt;/p&gt;

&lt;p&gt;Drift isn't a discipline problem. It's the structural consequence of writing the same fact in two places and hoping.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgyylp627osxoc52cqs7j.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgyylp627osxoc52cqs7j.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A third option: don't write it twice
&lt;/h2&gt;

&lt;p&gt;What if the deploy tool just &lt;em&gt;read&lt;/em&gt; your app?&lt;/p&gt;

&lt;p&gt;Your routes are already an HTTP API. A function you scheduled is already a scheduled job. A method you marked as consuming a queue is already a queue consumer. Those aren't hints about infrastructure — they &lt;em&gt;are&lt;/em&gt; the infrastructure, expressed in the language you were already writing in.&lt;/p&gt;

&lt;p&gt;That's the idea behind &lt;a href="https://laranja.io" rel="noopener noreferrer"&gt;laranja&lt;/a&gt; an open-source CLI I've been building. It reads your Express or NestJS source, works out what infrastructure it implies, and provisions it in &lt;strong&gt;your own AWS or Azure account&lt;/strong&gt; using &lt;strong&gt;your own local credentials&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No YAML. No second codebase. No CDK or Bicep to learn or install.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like
&lt;/h2&gt;

&lt;p&gt;Mark your app. That's the whole HTTP surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@alzulejos/laranja-decorators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/health&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;http&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ← the marker laranja looks for&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cron job from the intro, in full — no accompanying stack file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/jobs.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@alzulejos/laranja-decorators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;refreshCache&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;refreshing…&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;minutes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;refreshCache&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On NestJS you keep your DI, your modules, your constructor injection decorators sit on real providers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/event/queue.service.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Queue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@alzulejos/laranja-decorators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueueService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;mailer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Mailer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// real DI, untouched&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;emails&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;batchSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;sendEmails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmailJob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;laranja deploy

🍊 laranja · deploy my-api → eu-central-1
  🔑  account   123456789012
  📦  build     7 routes · 2 crons · 1 queue → 4 λ
  ✓ λ my-api-app-prod
  ✓ λ my-api-refreshCache-prod
  ✓ 📨 emails
  ✅ deployed &lt;span class="k"&gt;in &lt;/span&gt;38s

  🌐  http   https://abc123.lambda-url.eu-central-1.on.aws/
  ✨ live
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real Lambdas, a real Function URL, a real SQS queue with a real event source mapping — in your account, visible in your console, named &lt;code&gt;‹app›-‹fn›-‹stage›&lt;/code&gt; with no random suffixes. On Azure the same code becomes a Function App and a Storage Queue; you switch with one &lt;code&gt;provider&lt;/code&gt; field in the config, not a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things I'd want to know before trying it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It reads your code, it never runs it.&lt;/strong&gt; Discovery is static analysis, so &lt;code&gt;plan&lt;/code&gt; is always safe — nothing of yours executes just to work out what would be deployed. The tradeoff is that a few things have to be literal enough to see: &lt;code&gt;rate(5, "minutes")&lt;/code&gt; rather than a schedule computed at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your source stays on your machine.&lt;/strong&gt; laranja scans and bundles locally, then sends only a &lt;em&gt;description&lt;/em&gt; of the infrastructure the internal model plus asset hashes — to the server, which returns a CloudFormation or ARM template. Your code and your bundles don't cross the wire. Neither do your cloud credentials: the template is applied locally, by you, with whatever's on your standard credential chain (&lt;code&gt;aws configure&lt;/code&gt;, SSO, &lt;code&gt;az login&lt;/code&gt;). There's no IAM user to hand over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There's an exit.&lt;/strong&gt; &lt;code&gt;laranja eject&lt;/code&gt; gives you a real, owned infrastructure project. If the abstraction stops fitting you leave with working code rather than starting over. I'd rather you be able to walk away than be stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's an early MVP.&lt;/strong&gt; Express and NestJS, AWS and Azure, HTTP + crons + queues + env vars + stages. That's the honest scope today. APIs may still change. Internally the app is reduced to a framework- and provider-neutral model, which is how more of both are meant to land without changing how you write code but "meant to" is doing real work in that sentence, and I'd rather say so than imply the roadmap is already shipped.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual claim
&lt;/h2&gt;

&lt;p&gt;I'm not claiming IaC is bad. I've shipped a lot of CDK and I'd do it again for anything genuinely complex.&lt;/p&gt;

&lt;p&gt;The claim is narrower: &lt;strong&gt;for the common case — an API, some jobs, a queue — the infrastructure is fully determined by the app, and writing it out by hand is duplicated effort that decays into drift.&lt;/strong&gt; Deriving it removes an entire category of bug, because there's no second copy left to disagree with the first.&lt;/p&gt;

&lt;p&gt;Docs are at &lt;a href="https://laranja.io/docs" rel="noopener noreferrer"&gt;laranja.io/docs&lt;/a&gt;, and the client packages (CLI, decorators, and the libraries around them) are Apache-2.0 on GitHub.&lt;/p&gt;

&lt;p&gt;If you've solved this differently — or you think deriving infra from code is a bad idea and can say why — I genuinely want to hear it. That argument is more useful to me right now than stars.&lt;/p&gt;

</description>
      <category>node</category>
      <category>nestjs</category>
      <category>aws</category>
      <category>azure</category>
    </item>
    <item>
      <title>Deploy AWS Lambdas on different stages with Environment Variables using CircleCI</title>
      <dc:creator>Feras Allaou</dc:creator>
      <pubDate>Tue, 31 Mar 2020 09:17:58 +0000</pubDate>
      <link>https://dev.to/ferasallaou/deploy-aws-lambdas-on-different-stages-with-environment-variables-using-circleci-1m1k</link>
      <guid>https://dev.to/ferasallaou/deploy-aws-lambdas-on-different-stages-with-environment-variables-using-circleci-1m1k</guid>
      <description>&lt;p&gt;It might seem straight forward to deploy Lambda functions using CircleCI, and in fact it is. but in my case, I wanted to deploy Lambdas on different stages using the same CircleCI workflow, and what made it a bit challenging were Environment Variables because each stage has its own.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In this post, I am going to discuss two main points 1) securing env variables in Lambdas using CircleCI. 2) Having different variables for each stage.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Working with Env Variables
&lt;/h3&gt;

&lt;p&gt;The golden role in development says that env variables (.env or .secret files) should always be stored locally and not pushed to your Repo no matter. That means, if you are using .env file in your Project and wanted to deploy it to AWS Lambda using CircleCI, your .env file will be missing.&lt;/p&gt;

&lt;p&gt;You can add those env variables to your &lt;code&gt;serverless.yml&lt;/code&gt; file, but that one is also going to be in your Git repo, which returns us to point 1 again. Some might argue about using AWS Secret Manager, which is really a good solution but is a bit expensive, &lt;a href="https://aws.amazon.com/secrets-manager/pricing/" rel="noopener noreferrer"&gt;0.40$ for each key stored&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to solve that issue I went with creating my .env file on the go, while building the App before deploying it. The idea is really straight forward, you run a shell command to create .env&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;printf "NODE_ENV='$NODE_ENV'\nGOOGLE_MAPS_KEY='$GOOGLE_MAPS_KEY'
NODE_VERSION='$NODE_VERSION'\nYOU_NAME_IT='$YOU_NAME_IT'" &amp;gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when you package your app to deploy it on Lambda, .env file will be there for you. &lt;/p&gt;

&lt;p&gt;Well, this method has only one down side, your .env file might be readable inside your Lambda function. If you go to AWS Lambda functions' console, you can see Lambda files there, and of course, .env file will be a plain text. But simply restricting access to your Lambda functions will solve this issue, and if the Application is a bit big, Lambda will not load a preview for you, so you are safe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different Variables for Different Stages
&lt;/h3&gt;

&lt;p&gt;Well, the aforementioned method still has something missing, the real values, from where does shell grabs &lt;code&gt;$NODE_ENV&lt;/code&gt;'s value, no? and here where CircleCI Contexts becomes handy.&lt;/p&gt;

&lt;p&gt;In CircleCI, and in most CI/CD tools, you have the ability to store Env variables to use them while building and deploying. However, Contexts in CircleCI allows us to store Env variables securely; once you store the variable you cannot see its value in plain text.&lt;/p&gt;

&lt;p&gt;You can simply add the value of &lt;code&gt;$NODE_ENV&lt;/code&gt;, and other variables, there and it will be available for you while building and deploying, which now brings us to the second issue: How to have different Env variables for different stages in the same file?&lt;/p&gt;

&lt;p&gt;Contexts again is the answer here, because in Contexts you can create different projects and store different values inside each one. Then, we can call them inside CircleCI's config file before running any job like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;workflows:
  version: 2
  build-then-deploy:
    jobs:
      - build
      - build-test-app:
          context: app-dev #Context Name
          requires:
            - build
      - deploy-staging:
          context: app-staging #Context Name
          requires:
            - build-test-app
      - deploy-production:
          context: app-production #Context Name
          requires:
            - build-test-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be honest, I was stuck a bit in creating a reusable code to create env files, but using &lt;code&gt;commands&lt;/code&gt; I was able to solve this, and the code snippet looks something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commands:
  create-env-file:
    steps:
      - run:
          name: Create ENV File
          working_directory: myApp
          command: |
            printf "NODE_ENV='$NODE_ENV'\nGOOGLE_MAPS_KEY='$GOOGLE_MAPS_KEY'
            NODE_VERSION='$NODE_VERSION'\nYOU_NAME_IT='$YOU_NAME_IT'" &amp;gt; .env

version: 2.1
jobs:
  build:
    &amp;lt;&amp;lt;: *defaults
    steps:
      - checkout

  build-test-app:
    &amp;lt;&amp;lt;: *node-defaults
    steps:
      - create-env-file
      - run:
          name: Deploy App to DEV if Branch is Master
          working_directory: myApp
          command: |
            if [ "$CIRCLE_BRANCH" = "master" ];then
              sls deploy --stage development
            fi

  deploy-staging:
    &amp;lt;&amp;lt;: *node-defaults
    steps:
      - create-env-file
      - run:
          name: Deploy App to Staging if Branch is Master
          working_directory: myApp
          command: |
            if [ "$CIRCLE_BRANCH" = "master" ];then
              sls deploy --stage staging
            fi

  deploy-production:
    &amp;lt;&amp;lt;: *node-defaults
    steps:
      - create-env-file
      - run:
          name: Deploy App to Production if Branch is Master
          working_directory: myApp
          command: |
            if [ "$CIRCLE_BRANCH" = "master" ];then
              sls deploy --stage production
            fi

workflows:
  version: 2
  build-then-deploy:
    jobs:
      - build
      - build-test-app:
          context: app-dev #Context Name
          requires:
            - build
      - deploy-staging:
          context: app-staging #Context Name
          requires:
            - build-test-app
      - deploy-production:
          context: app-production #Context Name
          requires:
            - build-test-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;amp; Voila! &lt;/p&gt;

&lt;p&gt;Thanks for reading &amp;amp; I would like to hear and discuss different approaches as well.&lt;/p&gt;

</description>
      <category>circleci</category>
      <category>cicd</category>
      <category>devops</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
