<?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: Mark Ericksen</title>
    <description>The latest articles on DEV Community by Mark Ericksen (@brainlid).</description>
    <link>https://dev.to/brainlid</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%2F633428%2Fdb84aab1-661d-4625-a520-f3bd471ff76f.png</url>
      <title>DEV Community: Mark Ericksen</title>
      <link>https://dev.to/brainlid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brainlid"/>
    <language>en</language>
    <item>
      <title>Better Business Intelligence in Elixir with Livebook</title>
      <dc:creator>Mark Ericksen</dc:creator>
      <pubDate>Fri, 30 Jul 2021 16:57:02 +0000</pubDate>
      <link>https://dev.to/flyio/better-business-intelligence-in-elixir-with-livebook-pik</link>
      <guid>https://dev.to/flyio/better-business-intelligence-in-elixir-with-livebook-pik</guid>
      <description>&lt;p&gt;As a developer, has your manager ever come and asked a question like, "How much money are we making?" If you were a line-of-business developer at a global insurance company, you'd reach for your handy, nosebleed-expensive Business Intelligence (BI) suite to answer this question. But you're not, so how did you answer it for them?&lt;/p&gt;

&lt;p&gt;Obviously, you'd do what we all do. You'd SSH into your server, start an Elixir &lt;code&gt;iex&lt;/code&gt; session or a Rails console, then run some scripts to query data, sum numbers, and come up with answers.&lt;/p&gt;

&lt;p&gt;Well, give yourself a raise! Because you just built a  BI suite.&lt;/p&gt;

&lt;p&gt;It may not seem super sophisticated, but it solves the business need. And for problems like this, Livebook can be a better BI tool for Elixir developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  BI What?
&lt;/h2&gt;

&lt;p&gt;What is a &lt;a href="https://en.wikipedia.org/wiki/Business_intelligence"&gt;BI tool&lt;/a&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Business intelligence (BI) comprises the strategies and technologies used ... for the data analysis of business information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Translated from Gartner-speak, that means any tools you run to get a picture of how the business is doing are BI tools.&lt;/p&gt;

&lt;p&gt;In the last bootstrapped startup I worked at, management routinely asked backend developers for business numbers. It was simple stuff, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many new clients did we add this week?&lt;/li&gt;
&lt;li&gt;What was our customer's spend?&lt;/li&gt;
&lt;li&gt;Who are our top 10 customers this week and what were their numbers?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As simple as this stuff seems, it's really important for those business focused leaders to understand and make better decisions. That's why global insurance companies with applications that are too complicated to bring up a Rails console on spend six figures on BI suites.&lt;/p&gt;

&lt;p&gt;How did we get those answers? Using our Elixir &lt;code&gt;iex&lt;/code&gt;, or interactive shell. We ran some scripts and gave them CSV friendly rows they could add to their spreadsheets. In that early stage startup, we were using &lt;code&gt;iex&lt;/code&gt; as our BI tool. At a startup before that, we did the same thing but using the Rails console.&lt;/p&gt;

&lt;p&gt;If you're using the Rails console, Elixir's &lt;code&gt;iex&lt;/code&gt;, or another REPL to examine your data, then that's your BI tool for now. But with Elixir, we can do better. Livebook gives you data, charts and graphs too, but because it's executing your Elixir code, it can also call out to your other integrations and pull in even more.&lt;/p&gt;

&lt;p&gt;To understand why Livebook can be a better tool, let's go further and talk about BI tools in general, not just your REPL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Old School Business Intelligence
&lt;/h2&gt;

&lt;p&gt;Our premise in this post is that we can give "serious" BI tools a run for their money with Elixir and Livebook. Let's see what we're up against.&lt;/p&gt;

&lt;p&gt;Companies spend lots of money every year on their BI tools. You hear some of the numbers and it seems bananas. But it's because they &lt;em&gt;add&lt;/em&gt; a lot of value. Spotting trends in your data and customer behavior can make the difference of success and failure for a company.&lt;/p&gt;

&lt;p&gt;Most BIS tools are commercial. But there's a handful of credible open source projects. &lt;a href="https://www.metabase.com/"&gt;Metabase&lt;/a&gt;, for example, is an open source BI tool that works quite well. It connects directly to an application's database and helps you do some spelunking, aggregation, and  shiny graphing. You can even create and share custom dashboards. Think of it as Grafana, but for MBAs – it's a great tool.&lt;/p&gt;

&lt;p&gt;Deploying Metabase alongside your app might look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9vJCePKi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eqn1qzsfh0ff7d8x93nx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9vJCePKi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eqn1qzsfh0ff7d8x93nx.png" alt="Metabase app setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Metabase is an application that probably shouldn't be exposed publicly and it needs direct access to your database. It's also a bit of a mammoth – one doesn't just walk into Metabase and expect to get anything done, there's a real learning curve even when you know how to write SQL. It can be a heavy tool when you just want to do some quick poking around.&lt;/p&gt;

&lt;p&gt;It's also an app you need to keep running. We sell hosting, so we're generally OK with that. In fact, &lt;a href="https://www.metabase.com/docs/latest/operations-guide/running-metabase-on-docker.html"&gt;Metabase ships a Docker image&lt;/a&gt; and Fly lets you quickly &lt;a href="http://127.0.0.1:43579/docs/app-guides/run-a-global-image-service/#deploying-docker-images-to-fly"&gt;deploy apps using Docker&lt;/a&gt;. Money.&lt;/p&gt;

&lt;p&gt;This is fine when you want a dedicated data dashboard or you want to let non-developers see reports and graphs and be business-intelligent. However, when a project is young and you're a developer, digging with code is powerful. This is where Livebook can help!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is Livebook Better?
&lt;/h2&gt;

&lt;p&gt;Let's start with what Livebook is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/elixir-nx/livebook"&gt;Livebook&lt;/a&gt; started out as Elixir's version of &lt;a href="https://jupyter.org/"&gt;Jupyter Notebooks&lt;/a&gt;. Jupyter is pretty great. But it turns out that code notebooks on Elixir are something special; they do something you usually can't pull off in Python. That's because Elixir has powerful built-in clustering, built on Erlang's BEAM/OTP runtime. Livebook notebooks can talk directly to running Elixir apps.  And so we can do analysis and visualization directly off the models in our applications.&lt;/p&gt;

&lt;p&gt;Livebook really sings on Fly.io. We make it easy to deploy clusters of Elixir applications that can talk privately between themselves. More importantly: it's easy to bring up a secure &lt;a href="https://www.wireguard.com/"&gt;WireGuard&lt;/a&gt; tunnel to those applications. So I can run Livebook locally on my machine, and attach it to any of my apps running on Fly.io!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qFIxdd-Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/df8dx3q7mbi8gujmfcut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qFIxdd-Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/df8dx3q7mbi8gujmfcut.png" alt="Livebook remote connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For lean-and-mean startups, this is a win. You only need your app and your database running. Then, on an "as-needed" basis, you connect to your app with Livebook for analysis. Inside Livebook, analysis is done using your app's Elixir code. Livebook therefore doesn't need to connect directly to the database to run queries, and, even better, we get to re-use the business logic, associations, and schemas our apps already have.&lt;/p&gt;

&lt;p&gt;As a BI tool, Livebook notebooks  have these benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They use your application's code, like a REPL lets you.&lt;/li&gt;
&lt;li&gt;They have the ability to generate charts, graphics, and tables.&lt;/li&gt;
&lt;li&gt;Notebooks are markdown files and can be checked-in with your project. They can be shared with the team! No more, "I can't run the numbers today because Bill is out and he has the scripts."&lt;/li&gt;
&lt;li&gt;They are self-documenting because it's just markdown.&lt;/li&gt;
&lt;li&gt;They are designed to be highly reproducible. They are easy to re-run when you want updated numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of this you can pull off using just your REPL and some raw SQL queries. But why would you?   It's easier to use your project's code, database models (Ecto schemas for Elixir) and associations.&lt;/p&gt;

&lt;p&gt;Further,  your apps probably rely on external services like Stripe. Because Livebook talks directly to your Elixir code, you can query those external services with  that code, and then combine the results with your data. This is a combination that even dedicated tools like Metabase have a hard time beating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to Your App on Fly
&lt;/h2&gt;

&lt;p&gt;Great! You have a notebook that loads and visualizes some data! To get the benefits, you need to connect it to your app running on Fly.io.&lt;/p&gt;

&lt;p&gt;Follow the Fly.io &lt;a href="https://dev.to/docs/app-guides/elixir-livebook-connection-to-your-app/"&gt;Elixir Guide for Connecting Livebook to your App in Production&lt;/a&gt; to connect Livebook to your app.&lt;/p&gt;

&lt;p&gt;With Livebook connected to your app, you can run your notebook and start gaining insight to your data!&lt;/p&gt;

&lt;h2&gt;
  
  
  Gaining Intelligence
&lt;/h2&gt;

&lt;p&gt;How you use Livebook depends on your application and your industry.&lt;/p&gt;

&lt;p&gt;Here are some ideas to get the brain juices flowing. Each of these example notebooks would be a "module" in a serious commercial BI suite, and you'd pay $45k for a license for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  User Account Setup
&lt;/h3&gt;

&lt;p&gt;How many of your users have fully set up their accounts?&lt;/p&gt;

&lt;p&gt;Build and share a notebook that tracks where users are in your onboarding process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Users Bouncing From The App
&lt;/h3&gt;

&lt;p&gt;Where are accounts stalling out in onboarding?&lt;/p&gt;

&lt;p&gt;Graph the stages accounts are at and let analysts drill into the onboarding funnel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sales Analysis
&lt;/h3&gt;

&lt;p&gt;How were sales for your products or services last month?&lt;/p&gt;

&lt;p&gt;Graph a multi-series chart comparing sales across products.&lt;/p&gt;

&lt;p&gt;What about total sales per week?&lt;/p&gt;

&lt;p&gt;Build a notebook with a date input making it easy to switch the week being charted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrations
&lt;/h3&gt;

&lt;p&gt;What external financial systems are you integrated with?&lt;/p&gt;

&lt;p&gt;Notebooks can execute your code to query those services and visualize refund rates, processing fees, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;What's great about the Livebook approach is you are writing working Elixir code. When you are ready to build an Admin Dashboard page in your app, you've already done the hard work of figuring out what data is valuable and even the code for how to get it!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>livebook</category>
      <category>startup</category>
    </item>
    <item>
      <title>Monitoring Elixir Apps on Fly.io With Prometheus and PromEx</title>
      <dc:creator>Mark Ericksen</dc:creator>
      <pubDate>Tue, 29 Jun 2021 20:06:15 +0000</pubDate>
      <link>https://dev.to/flyio/monitoring-elixir-apps-on-fly-io-with-prometheus-and-promex-5gn6</link>
      <guid>https://dev.to/flyio/monitoring-elixir-apps-on-fly-io-with-prometheus-and-promex-5gn6</guid>
      <description>&lt;p&gt;Fly.io takes Docker containers and converts them into fleets of Firecracker micro-vms running in racks around the world. If you have a working Docker container, you can run it close to your users, whether they're in Singapore or Amsterdam, with just a couple of commands. Fly.io is particularly nice for Elixir applications, because Elixir's first-class support for distributed computing meshes perfectly with Fly.io's first-class support for clusters of applications.&lt;/p&gt;

&lt;p&gt;This post is about another cool Fly.io feature --- built-in Prometheus metrics --- and how easy it is to take advantage of them in an Elixir application. I wrote and maintain &lt;a href="https://github.com/akoutmos/prom_ex"&gt;an Elixir library, PromEx&lt;/a&gt;, that makes it a snap to export all sorts of metrics from your Elixir applications and get them on dashboards in Grafana. Let's explore some of the concepts surrounding Prometheus and see how we can leverage the Fly.io monitoring&lt;br&gt;
tools in an Elixir application to get slick looking dashboards like this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MmAL6tG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89aey5grf5lmm23gjl00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MmAL6tG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89aey5grf5lmm23gjl00.png" alt="Phoenix Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Application Monitoring is Important
&lt;/h2&gt;

&lt;p&gt;When customers are paying for your application or service, they expect it to work every time they reach for it. When things break or errors occur, your customers will not be happy. If you are lucky, your customers send you an email letting you know that things are not working as expected. Unfortunately, many of these occurrences go unreported.&lt;/p&gt;

&lt;p&gt;Knowing exactly when things are going wrong is key to keeping your customers happy. This is the problem that monitoring tools solve. They keep an eye on your application, and let you know exactly when things are behaving suboptimally.&lt;/p&gt;

&lt;p&gt;Imagine for example that you have an HTTP JSON API. You deploy a new version that changes a bunch of endpoints. Assume it's  infeasible to go through every single route of your application every time you deploy,  or to test each endpoint individually with every permutation of input data. That would take far too much time, and it doesn't scale from an organizational perspective: it would keep engineers constantly context switching between feature work and testing new deployments. &lt;/p&gt;

&lt;p&gt;A more scalable solution: briefly smoke test the application after a deployment (as a sanity check), and then use monitoring tooling to pick up on and report on any errors. If your monitoring solution reports that your HTTP JSON API is now responding with 400 or 500 errors, you know you have a problem and you can either rollback the application, or stop it from propagating to across the cluster. The key point is that you can proactively address issues as opposed to being blind to them, and at the same time you can avoid sinking precious engineer time into testing all the things.&lt;/p&gt;

&lt;p&gt;While ensuring that production users are not experiencing issues is a huge benefit of application monitoring, there are lots of other benefits. They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quantifying stress testing results&lt;/li&gt;
&lt;li&gt;Business priority planning based on real usage data&lt;/li&gt;
&lt;li&gt;System performance and capacity planning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dig into how Prometheus achieves these goals at the technical level.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Does Prometheus Work?
&lt;/h2&gt;

&lt;p&gt;At its core, Prometheus is a time-series database that enables you to persist metrics in an efficient and performant manner. Once your metrics are in the Prometheus time-series database, you can create alerting rules in Grafana. Those alerts can then be triggered once certain thresholds and criteria are met, letting you know that something has gone wrong.&lt;/p&gt;

&lt;p&gt;"But how exactly do my application metrics end up in Prometheus?" Well, your Prometheus instance is configured to scrape all of your configured applications. At a regular interval, each of their instances is &lt;a href="https://fly.io/blog/measuring-fly/"&gt;queried for metrics data, which is stored in a database&lt;/a&gt;. Specifically, it makes a GET HTTP call to &lt;code&gt;/metrics&lt;/code&gt; (or wherever your metrics are exposed) and that endpoint will contain a snapshot in time of the state of your application. Once your metrics are in Prometheus, you can query the time-series database with Grafana to plot the data over time; Grafana uses PromQL to refresh data and update its panels.&lt;/p&gt;

&lt;p&gt;Given that Prometheus scrapes your applications at a regular interval, the resolution of your time-series data is bound to that interval. In other words, if you get 1,000 requests in&lt;br&gt;
the span of 10 seconds, you don't know exactly at what timestamps those 1,000 requests came in, you just know that you got 1,000 requests in a 10 second time window. While this may seem limiting, it is actually a benefit in disguise. Since Prometheus doesn't need to keep track of every single timestamp, it is able to store all the time-series data very efficiently.&lt;/p&gt;

&lt;p&gt;Luckily with Fly.io, the administration and management of Prometheus can be taken care of for you!&lt;/p&gt;
&lt;h2&gt;
  
  
  Turning On Prometheus On Fly
&lt;/h2&gt;

&lt;p&gt;Managing, configuring and administering your own Prometheus instance can be a bit of a tall order if you have never worked with Prometheus before. Fortunately, all you need to do to enable Prometheus metrics for your application is add a couple of lines to your &lt;code&gt;fly.toml&lt;/code&gt; manifest file. All Fly.io needs to know is what port and path your metrics will be available at. For the &lt;a href="https://github.com/fly-apps/elixir_prom_ex_example/tree/master/todo_list"&gt;TODO List Elixir application&lt;/a&gt; for example, the following configuration was all that was needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[metrics]&lt;/span&gt;
&lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;
&lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/metrics"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to visualize your Prometheus metrics, you'll need to have an instance of Grafana running somewhere. You could deploy your own Grafana instance on Fly.io by &lt;a href="https://github.com/fly-apps/grafana"&gt;following this guide&lt;/a&gt;, but you can also use &lt;a href="https://grafana.com/products/cloud/"&gt;Grafana Cloud&lt;/a&gt; (it has a free plan) --- Grafana Cloud works fine with Fly. Which ever route you take, all you then need to do is configure Grafana to &lt;a href="https://fly.io/docs/reference/metrics/#grafana"&gt;communicate with the Fly.io managed Prometheus instance&lt;/a&gt; and you are good to go!&lt;/p&gt;

&lt;p&gt;Now that we've got Prometheus hooked up, we need to get our Elixir application to start providing metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring Elixir with PromEx
&lt;/h2&gt;

&lt;p&gt;Whenever I write a production-grade Elixir application that needs monitoring, I reach for &lt;a href="https://github.com/akoutmos/prom_ex"&gt;PromEx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wrote PromEx and maintain it because I wanted something that made it easy to manage both the collection of metrics and the lifecycle of a a bunch of Grafana dashboards. That's to say: PromEx doesn't just export Prometheus metrics; it also provides you with dashboards you can import into Grafana to immediately get value out of those metrics. I think this is a pretty ambitious goal and I'm happy with how it turned out. Let's dig in.&lt;/p&gt;

&lt;p&gt;At a library design level, PromEx is a plugin style library, where you enable a plugin for whatever library you want to monitor. For example, PromEx has plugins to capture metrics for Phoenix, Ecto, the Erlang VM itself, Phoenix LiveView and several more. Each of these plugins also has a dashboard to present all the captured metrics for you. In addition, PromEx can communicate with Grafana using the Grafana HTTP API, so it will upload the dashboards automatically for you on application start (if you configure it that is). What this means is that you can go from zero to complete application metrics and dashboards in less that 10 minutes!&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/fly-apps/elixir_prom_ex_example/tree/master/todo_list"&gt;Elixir example application&lt;/a&gt;, you can see that the PromEx module definition specifies what plugins PromEx should initialize, and what dashboards should be uploaded to Grafana:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;TodoList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PromEx&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;PromEx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:todo_list&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;PromEx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Plugins&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;# PromEx built in plugins&lt;/span&gt;
      &lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Beam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Phoenix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;router:&lt;/span&gt; &lt;span class="no"&gt;TodoListWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PhoenixLiveView&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dashboard_assigns&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="ss"&gt;datasource_id:&lt;/span&gt; &lt;span class="s2"&gt;"prometheus"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dashboards&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;# PromEx built in Grafana dashboards&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:prom_ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"application.json"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:prom_ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"beam.json"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:prom_ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"phoenix.json"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:prom_ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"phoenix_live_view.json"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a little bit of configuration in &lt;code&gt;runtime.exs&lt;/code&gt; PromEx can communicate with Grafana to take care of the graph annotations and dashboard uploads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:todo_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TodoList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;PromEx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;manual_metrics_start_delay:&lt;/span&gt; &lt;span class="ss"&gt;:no_delay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;grafana:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="ss"&gt;host:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"GRAFANA_HOST"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"GRAFANA_HOST is required"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;auth_token:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"GRAFANA_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"GRAFANA_TOKEN is required"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;upload_dashboards_on_start:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;folder_name:&lt;/span&gt; &lt;span class="s2"&gt;"Todo App Dashboards"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;annotate_app_lifecycle:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the managed Prometheus instance from Fly.io, and the metrics collection from PromEx, you have an instrumented application in record time! Here are some snapshots from the auto generated dashboards for the &lt;a href="https://github.com/fly-apps/elixir_prom_ex_example/tree/master/todo_list"&gt;Todo List application&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8YBkv94i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wn93dmlk2qled56zcev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8YBkv94i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wn93dmlk2qled56zcev.png" alt="Erlang VM Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7z8t1RAk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1yr51wqs389uwdunl2l8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7z8t1RAk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1yr51wqs389uwdunl2l8.png" alt="Phoenix LiveView Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  And That's It!
&lt;/h2&gt;

&lt;p&gt;Elixir makes it easy to run ambitious, modern applications that take advantage of distributed computing. It should be just easy easy to see what those applications are actually doing, and to have alerts go off when they misbehave. Between Fly.io's built-in Prometheus and the PromEx library, it's easy to get this kind of visibility. Your application can be instrumented with dashboards and annotations in a coffee break's worth of time.&lt;/p&gt;

&lt;p&gt;Be sure to check out the &lt;a href="https://github.com/fly-apps/elixir_prom_ex_example/tree/master/todo_list"&gt;Todo List application Repo&lt;/a&gt; for more technical details and all the code necessary to do this yourself. What used to take a few days to set up and run, now only takes a few hours, so be sure to give it a test drive!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>metrics</category>
    </item>
    <item>
      <title>Observing Elixir in Production</title>
      <dc:creator>Mark Ericksen</dc:creator>
      <pubDate>Wed, 16 Jun 2021 21:25:05 +0000</pubDate>
      <link>https://dev.to/brainlid/observing-elixir-in-production-56aa</link>
      <guid>https://dev.to/brainlid/observing-elixir-in-production-56aa</guid>
      <description>&lt;p&gt;Fly networking lets you VPN in and run Observer directly in production. &lt;a href="https://fly.io/docs/getting-started/elixir/" rel="noopener noreferrer"&gt;Deploy your Elixir application and try it out!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elixir, Erlang, and really just the BEAM has a feature called "&lt;a href="https://elixir-lang.org/getting-started/debugging.html#observer" rel="noopener noreferrer"&gt;Observer&lt;/a&gt;". It's fun showing it to people new to Elixir because it's just so cool! It's a WxWidgets graphical interface that connects in realtime to a running Erlang node and lets you "observe" what's going on. It has some limited ability to modify things as well, most notably you can kill running processes. This can help when something is misbehaving or you just want to play "chaos monkey" and kill parts of the system to see how it recovers.&lt;/p&gt;

&lt;p&gt;This picture shows a process tree for the application. Using this I can inspect individual processes or even kill them!&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%2F35cdhngddmrref9g0apf.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%2F35cdhngddmrref9g0apf.png" alt="Running GameServer highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One very cool way to run Observer is to run it on your local machine (which has the ability to display the UI) and connect to a production server (with no windowing UI available) and "observe" it from a distance. So yeah... have a problem in production? Not sure what's going on? You can tunnel in, crack the lid and poke, prod, and peek around to see what's going on.&lt;/p&gt;

&lt;p&gt;The Fly platform makes it easy to do this for your own applications!&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Will Do
&lt;/h2&gt;

&lt;p&gt;Fly.io natively supports &lt;a href="https://www.wireguard.com/" rel="noopener noreferrer"&gt;WireGuard&lt;/a&gt;, Jason Donenfeld’s amazing VPN protocol. If you’ve ever lost hours of your life trying to set up an IPSec VPN, you’ll be blown away by how easy WireGuard is. It’s so flexible and performant that Fly uses it as our network fabric. And it’s supported on &lt;a href="https://www.wireguard.com/install/" rel="noopener noreferrer"&gt;every major platform&lt;/a&gt;, including macOS, iOS, Windows, and Linux. What that means for you is that if your app runs on Fly, you can open a secure, private, direct connection from your dev machine to your production network, in less time than it took me to write this paragraph. Cool, right?&lt;/p&gt;

&lt;p&gt;This is what we're going to do.&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%2Fq5qy9nskqk40h5v9xzr2.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%2Fq5qy9nskqk40h5v9xzr2.png" alt="WireGuard observer connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will bring up a secure WireGuard tunnel that links to your servers on Fly. In this graphic, there are two &lt;code&gt;my_app&lt;/code&gt; Elixir nodes clustered together running on Fly.&lt;/p&gt;

&lt;p&gt;From the local machine, we can open an &lt;code&gt;IEx&lt;/code&gt; terminal configured to &lt;strong&gt;join&lt;/strong&gt; that cluster of remote Elixir nodes. Our local machine supports running Observer and drawing the UI. We use our local observer to talk to the remote nodes in the cluster!&lt;/p&gt;

&lt;h2&gt;
  
  
  Making It Happen
&lt;/h2&gt;

&lt;p&gt;To test this out, I follow &lt;a href="https://fly.io/docs/app-guides/elixir-observer-connection-to-your-app/" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; and apply the changes to the multi-region &lt;a href="https://fly.io/blog/building-a-distributed-turn-based-game-system-in-elixir/" rel="noopener noreferrer"&gt;Tic-Tac-Toe game created here&lt;/a&gt;. The github repo for the &lt;a href="https://github.com/fly-apps/tictac" rel="noopener noreferrer"&gt;project is here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's what we do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure an Elixir release to use a cookie value we provide.&lt;/li&gt;
&lt;li&gt;Setup WireGuard for Fly. This is a VPN technology that let's us directly connect to the production private network.&lt;/li&gt;
&lt;li&gt;Create a simple script to launch Observer for us.&lt;/li&gt;
&lt;li&gt;Launch Observer and explore!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Again, follow the &lt;a href="https://fly.io/docs/app-guides/elixir-observer-connection-to-your-app/" rel="noopener noreferrer"&gt;guide here&lt;/a&gt; for a step-by-step breakdown of how to do it for your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Region Support?
&lt;/h2&gt;

&lt;p&gt;When Elixir nodes are clustered together and running in different regions, Observer can connect to any node in the cluster.&lt;/p&gt;

&lt;p&gt;After making the changes to the TicTac project and deploying it to multiple regions, let's see what it looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fly status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

Instances
ID       VERSION REGION DESIRED STATUS  HEALTH CHECKS      RESTARTS CREATED
79510f86 17      fra    run     running 1 total, 1 passing 0        23m39s ago
df93ea35 17      lax(B) run     running 1 total, 1 passing 0        24m3s ago
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have the game scaled out to &lt;a href="https://fly.io/docs/reference/regions/" rel="noopener noreferrer"&gt;two regions&lt;/a&gt;. One is running in &lt;code&gt;fra&lt;/code&gt; (Frankfurt, Germany) and the other is running in &lt;code&gt;lax&lt;/code&gt; (Los Angeles, California (US)).&lt;/p&gt;

&lt;p&gt;When I open Observer locally, I see two remote instances of &lt;code&gt;tictactoe&lt;/code&gt;!&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%2Fy5uctsxrri90bly22423.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%2Fy5uctsxrri90bly22423.png" alt="Instances in different regions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring My App
&lt;/h2&gt;

&lt;p&gt;I start playing a game on the web and use Observer to browse around and find the game. It's highlighted in blue and linked from &lt;code&gt;GameRegistry&lt;/code&gt;.&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%2F8ffpy6d2scotosntj7tw.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%2F8ffpy6d2scotosntj7tw.png" alt="Running GameServer highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using Observer, I can double-click the selected game process and even view the GenServer's state. This gives a snapshot of the state at the time I double-clicked it. I highlighted in yellow some interesting parts of the game state.&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%2F37025so2n945j0pvdr13.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%2F37025so2n945j0pvdr13.png" alt="Game state displayed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're wondering why the state data looks strange (at least different from Elixir), it's because that's the Erlang representation of those data types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Playing Chaos Monkey
&lt;/h2&gt;

&lt;p&gt;Something fun you can do with Observer is identify processes, inspect them, and even kill them. This can help when something is misbehaving and you want to see more about what's going on. This can also help you test how your system recovers from unexpected failures.&lt;/p&gt;

&lt;p&gt;I've already identified the running game process. By right-clicking it I see I have the option to "kill" it. What will happen when a game server dies?&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%2F9ag9rwm1relx2ll3j9cb.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%2F9ag9rwm1relx2ll3j9cb.png" alt="Kill process menu option"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After killing the game process, I see that a new process was immediately started. How can I tell? The PID (Process ID) value is different.&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%2Fuwhlshepeysfnuwbztfu.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%2Fuwhlshepeysfnuwbztfu.png" alt="Process restarted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, it looks like my system isolates the damage in that no other running games are impacted when one crashes. Yay! My system stays up and running!&lt;/p&gt;

&lt;p&gt;From the user's perspective playing the game, it's not so graceful.  The player &lt;strong&gt;is&lt;/strong&gt; able to recover but it requires them to reload their page or restart the game joining processing. I see that my UX can be improved to make crash recovery better for the user.&lt;/p&gt;

&lt;p&gt;That was a productive experiment!&lt;/p&gt;

&lt;h2&gt;
  
  
  Now You Try
&lt;/h2&gt;

&lt;p&gt;Deploy a Phoenix application to Fly, setup your WireGuard VPN, and start observing your app in production!&lt;/p&gt;

&lt;p&gt;With Elixir you can build resilient systems! Fly makes observing them easy. What will you find digging around in the state pile?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fly.io/docs/getting-started/elixir/" rel="noopener noreferrer"&gt;Deploy your Elixir App!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>wireguard</category>
      <category>clustering</category>
    </item>
    <item>
      <title>ThinkingElixir 049: Pushing for Modularity with Maciej Kaszubowski</title>
      <dc:creator>Mark Ericksen</dc:creator>
      <pubDate>Tue, 25 May 2021 12:35:40 +0000</pubDate>
      <link>https://dev.to/brainlid/thinkingelixir-049-pushing-for-modularity-with-maciej-kaszubowski-4h54</link>
      <guid>https://dev.to/brainlid/thinkingelixir-049-pushing-for-modularity-with-maciej-kaszubowski-4h54</guid>
      <description>&lt;p&gt;In episode 49 of &lt;a href="https://thinkingelixir.com/the-podcast/"&gt;Thinking Elixir&lt;/a&gt;, &lt;a href="https://github.com/mkaszubowski94"&gt;Maciej Kaszubowski&lt;/a&gt; returns to talk about how read models can help modularize our systems. There is a focus on background job systems and how they fit in our modular designs. We cover push vs pull based systems and which is more maintainable. Maciej also shares his approach to learning and understanding a new Elixir library and more!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://thinkingelixir.com/podcast-episodes/049-pushing-for-modularity-with-maciej-kaszubowski"&gt;Podcast Episode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>architecture</category>
    </item>
    <item>
      <title>ThinkingElixir 048: Ecto Associations with Sheharyar Naseer</title>
      <dc:creator>Mark Ericksen</dc:creator>
      <pubDate>Tue, 18 May 2021 12:24:50 +0000</pubDate>
      <link>https://dev.to/brainlid/thinkingelixir-048-ecto-associations-with-sheharyar-naseer-4bhi</link>
      <guid>https://dev.to/brainlid/thinkingelixir-048-ecto-associations-with-sheharyar-naseer-4bhi</guid>
      <description>&lt;p&gt;In episode 48 of &lt;a href="https://thinkingelixir.com/the-podcast/"&gt;Thinking Elixir&lt;/a&gt;, we talk with &lt;a href="https://twitter.com/sheharyarn"&gt;Sheharyar Naseer&lt;/a&gt; about Ecto’s feature “association defaults” and how they work. They support defining a function that gets called during your changeset operations and can be used to ensure that multi-tenancy IDs get populated down correctly. We learn more about Slab, talk about Single Table Inheritance designs and how we feel about them. We also talk about wrapping our Repo module for fun and profit!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://thinkingelixir.com/podcast-episodes/048-ecto-associations-with-sheharyar-naseer"&gt;Podcast Episode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>database</category>
    </item>
  </channel>
</rss>
