Hey folks, this one is a quick one, but first: I have a speed bump phobia. But I'm slowly getting over it now, which is nice. Now, a quick suggestion: Store your SSH keys in a password manager, folks! The Problem It feels like every day, there's a new NPM hack that installs a malicious package on a developer's machine that steals their credentials, especially the private SSH keys that can be used…
Hey folks, let's start with a ceremonial dad joke: The worst job I ever had was ranking soft drinks in order of fizziness. It was soda grading Alright, now: What's going on with all these CVEs, Peter?! The Beginning When I went to ElixirConf EU in Málaga a few weeks back, I had quite a few conversations about the impact of LLMs on the security of our industry. Basically, everyone was scared of…
Hey folks! First, a joke: What’s the worst vegetable to bring on a boat? A leek Now, let's talk about devcontainers for Elixir. The Problem Claude now writes 95% of my code. I've been lukewarm about the whole "AI" hype until Opus 4.5 was released. It was a game-changer for me. Sonnet was alright for small stuff with very guided instructions and it was a small net benefit for me, but Opus 4.5 was…
Hey folks, welcome back! First a joke: Why did the Mexican start taking anti-anxiety medication? For Hispanic attacks Now, a quick tip on how to notify yourself if someone (hopefully yourself) logs into your server using SSH. The Problem I've migrated all my apps from various hosting providers to my own Hetzner bare metal server recently. It works fantastically, but now with all my eggs in a…
Welcome back, friends! Did you hear the news about the inventor of the Knock-Knock joke? He got a No-bell prize. Alright, this post will be a bit longer since we'll dive deeply into the Postgres WAL and will explore how to listen for database changes through it. The Problem Let's say you want to react to changes in your Postgres database, for example to send out realtime notifications or to track…
Welcome back! First, a joke: Don’t trust atoms They make up everything Now, onto today's topic: Binary Pattern Matching in Elixir The Gist Pattern matching in Elixir is a superpower you probably know about, but chances are that you haven't encountered its little brother, binary pattern matching yet. Let's fix that. In essence, Elixir makes it incredibly easy to deconstruct binaries into their more…
Hey folks! Let's warm up with a joke: It is forbidden to laugh out loud in Hawaii. You have to keep it to a low ha. A low ha. Aloha. Got it? Good! Let's begin. The Problem Let's say you want to store a map in an Ecto.Schema . You add a :map field which Ecto converts into an optimized jsonb column in Postgres. You trust the awesomeness of Postgres and start dumping data into it. Everything works…
Welcome to another blog post, folks! First another dad joke: What do you call a medieval spy? Sir Veillance Alrighty, today's a quick one. How to assert that an async task succeeds eventually in your Elixir tests. The Problem Elixir makes writing asynchronous work easy, but testing it is still a bit tricky. Let's have a look at an example test: test "async task updates my database record…
Welcome everyone to the new year! Let's start it the right way with a joke: What do you call a fruit that magically shows up? A pear Now, let's dive into today's topic: How to white-label a software using Gettext domains. The Problem Imagine you develop a white-label HR software and you want to customise the way your software addresses the "user" depending on the company they work for. Most…
Hey folks, today's blog post is slightly longer than usual, but it'll be worth it. To get you started, let me ask you: Did you hear about the Italian chef who died? He pasta-way Alrighty, let's dig in! The Problem A few weeks back, I watched Chris McCord live-code a Twitch clone during the Elixir Stream Week . He implemented an architecture which received the video stream of a creator on one…
Today's post is a tiny one. I recently added a configuration option to Phx2ban that allows users to define routes that should be excluded from the Web Application Firewall (WAF) rules of Phx2ban. Basically, any request to any of the given routes should be ignored. I wanted to allow the user to define the routes as strings ( /my-path/foo ) but also as regex ( ~r/my-path/* ). We use NimbleOptions to…
It feels like the eXodus of the Elixir community from X to Bluesky is in full swing. Even if you don't want to abandon X yet, setting up camp on Bluesky is a smart choice. I wrote this guide to make the switch easier for you. Here's how to join the Elixir community on Bluesky and some key terms you should know about. 1. How to sign up Just go to bsky.app and create an account. Don't worry if your…
Hey folks, today's article is a quick one, but let me start with the obligatory dad joke: What's red and bad for your teeth? A brick Alrighty, today's post is about a quick and easy approach to mocking in Elixir tests. Update: After publishing this blog post, my good friend and favourite nit-picker, Tobi Pfeiffer, pointed out on X that the "Mock" described here is actually a Stub. Unsurprisingly,…
Welcome to another blog post! First, an excerpt from my life: A bike in town keeps running me over. It’s a vicious cycle. Alrighty, now let's dive into today's topic: Using the Saga Pattern in Elixir. The Problem If you build software long enough, you will eventually encounter use cases that require multiple steps to succeed before the overall process can be considered "complete". If any of the…
Hey folks, welcome back! After such a long time without a blog post from me, you might ask yourself: When is a joke a dad joke? When it's apparent. Anyway, let's get started with today's topic: Why you shouldn't kill your Phoenix context and - in fact - resurrect it! A Retraction In June 2023, I wrote a blog post titled Kill your Phoenix Context in which I proposed a new software design for…
Hello there fellow Elixirists! It's been a while since my last blog post which is largely the fault of my new startup indiecourses.com which takes up all my previous blog-writing time! To show my apologies, please accept the following dad joke: I got pulled over by a police officer. He looked at my license and said I should wear glasses. I said I have contacts. He said he doesn’t care who I know.…
Hey everyone, Today's article is sponsored by Tigris . They were so kind to give me beta access to their globally distributed S3-compatible Object Storage before their public beta launch. Tigris partners with Fly.io to distribute your files globally, which makes accessing them anywhere in the world super fast. Tigris is an excellent drop-in solution if you use S3 and give users access to your…
Welcome back to another article! Let's end the year with one last dad joke: My boss asked me why I only get sick on work days. I said it must be my weekend immune system. Alrighty! Let's dive into today's topic: How to resize and host user-provided images with Cloudflare Images. The Problem For my startup Indie Courses , I recently ran into the issue that I had to handle user-provided images. In…
Welcome back to another article! Let's start with the mandatory dad joke: Apparently you can’t use “beef stew” as a password. It’s not stroganoff. Alright, now let's talk about a small but important topic: How to build emails with Swoosh and send them through Oban background workers. The Problem Almost all applications have to send emails. Whenever somebody registers or buys something, you send…
I'm happy to announce that after five years of working full-time, I'll hang up my employee hat and put on the chaos stress halo of a freelancer and startup entrepreneur. At least until I run out of money or my hair falls out, whatever comes first 😄 So, here's what comes next Through my network, I was referred to a very interesting Elixir freelance job where I'll work 2 days a week. That's gonna…
Hey there! Let me welcome you with the customary dad joke: What do you call a knight made entirely out of fine china? Sir Ramic Alright! Now, let's dive into today's topic: How to test an external, read-only Database connection in Phoenix. The Problem Sometimes, we have to connect our Elixir applications to read from an external database that we don't control. Setting up the connection is easy.…
Hello there (General Kenobi), it's been a while since the last blog post! Let me apologise with a ceremonial dad joke: I can tolerate algebra, maybe even a little calculus. But geometry is where I draw the line. Alright then! Today's blog post is a very small cheatsheet for how to work with files in Livebook. Let's get started! Upload Here's a quick overview, the code is below: To upload a file to…
Welcome back to another blog post! Before we begin, one question: When a building goes to a party, what does it wear? Address! Alright. Yesterday, I tweeted about my struggles to animate a side drawer in LiveView. You folks asked me to write about it, so here's a quick dive into how to animate a side drawer using Phoenix.LiveView.JS The Setup Our setup is pretty simple: We have a full-width div…
Hey folks, welcome back to another blog post! Did you know that: When you go into the bathroom, you're American. When you come out of the bathroom, you're American. But what are you IN the bathroom? European! Anyways, today's blog post touches on a topic that I've written about plenty already. It's about efficient name search in Postgres, but with a twist! The Problem In previous articles, I wrote…
Welcome back, folks! My girlfriend broke up with me when she found out I only had 9 toes. She was lack toes intolerant. Alright. Today, we'll take a look at security issues when using third-party libraries in your Elixir applications. If you add libraries to your application, you could get robbed of all your secrets and user data. I'll show you what a malicious library could look like and how you…
Hey folks, welcome back to another blog post! :) First, as always, the ceremonial dad joke: What do you call a typo on a headstone? A grave mistake. Anyways! This post is a mini-rant about Phoenix Contexts and how not to use them. Enjoy! Retraction Watch out : I retracted this blog post because I changed my mind about Phoenix contexts lately. Read my retraction which includes my new favorite…
Hey folks, welcome back to another blog post! :) I'm sorry for the delay since my last blog post, but I've been busy with creating my video course Build an MVP with Elixir and speaking at ElixirConf EU in Lisbon. But now I'm back and will post new blog posts every two weeks again. So, before we dive into today's blog post, first the ceremonial dad joke: I don't have a dad body. I have a father…
Hey folks! I've got an exciting announcement to make! I've just launched my very first video course titled Build an MVP with Elixir ! Whether you're a newbie developer or a seasoned pro looking to get into Elixir, this course will teach you how to get started! The course shows you how to quickly develop and deploy a product using Elixir and Phoenix LiveView. It takes a learning-by-doing approach…
Welcome back to another blog post :) Before we begin, one question: Why do cows have hooves instead of feet? Because they lactose! Alright, now let's dive into today's topic: How to listen to database changes using Postgres triggers and Elixir Why listen at all? In almost all codebases, you have subsequent processes depending on previous processes. Imagine a sign-up flow for new users. After a…
Hey folks, before we begin: Where do dads store their jokes? In the dad-a-base Alright 😄 Let's get started with today's topic: How to build dynamic forms with JSON schemas Why JSON Schemas As I wrote in my book , probably 50% of a software engineer's time is spent building tables. The other 50% is spent on building forms. This article covers how to build forms faster. Imagine that you have to…
Hey folks, today we'll learn how to set up the latest Livebook version 0.8 and use the new Neural Network smart cell. You can find more information about this topic in the announcement here . Let's get started! Install Livebook 0.8 First, we need to update our local Livebook installation. If you haven't installed Livebook yet, please follow this installation guide . I typically install and update…
Hey folks, this is the second part of a mini-series about building a roles and permissions (RAP) system for Phoenix. If you haven't read the first part yet, please go here and read it first :) In the first post of this mini-series, we learned how to implement basic permissions for your schemas, how to group them into roles, and how to assign the roles to our users. We used the role to check a…
Hey folks, before we begin: Salespeople can be persistent, can't they? The other day, one tried to sell me a coffin. I told him that's the last thing I need! Anyways. Today, we'll look into how to set up a basic roles and permissions (RAP) system with Phoenix and Ecto. I got this idea from my dear ex-colleague Lucas and my current colleagues Vitor and Antonio , who built the backend part of our…
Hey folks 👋 Before we begin, a little story: My friend bragged that his 3D printer could print a Gun, but I wasn’t impressed. I already had a Canon printer for years! Alright, now to today's topic: How to simulate latency, jitter, and package loss when developing LiveView apps The Problem When we develop LiveView apps, usually two things are true: We develop it locally and we test production…
Before we begin, my apologies for the delay in publishing this article. This year's flu season hit me pretty hard. But being sick reminded me of an odd experience I made recently: Someone called me on my phone, sneezed, and then hung up. To be honest, I'm getting sick and tired of these cold calls! Anyways. Let's dive into today's topic: Efficient full-text search with Postgres and Ecto ! The…
Hey folks, before we begin, a public service announcement: Respect people who wear glasses. They paid money to see you. Okay, that was enough fun for today. Let's dive into today's topic: How can you search through millions of usernames using Ecto and Postgres? Let's find out! Quick note: This article does not cover full-text search (FTS) with Postgres. It focuses only on searching for short…
Happy whatever day you're reading this! Before we begin, let me ask you: What's the best present you can ever give? A broken drum. Nobody can beat that. Alright. Now, let's get down to business. Here's another question for you: Imagine you build an appointment scheduling service. A service that allows patients to book an appointment with their doctor. You want to prevent double-booking of a doctor…
Before we start talking about using placeholders in Ecto's insert_all/3 , I need you to understand the following: What do you call cheese that is not yours? Nacho Cheese Now, with the ceremonial dad joke out of the way, let's focus on today's topic: What are Ecto placeholders and how to use them when inserting a lot of data? The Problem Imagine we want to insert a lot of book data into our…
Before we dive into today's blog post, please consider the following question: What has two butts and kills people? The answer is obvious: An assassin Just as assassins have two butts, we will also talk about two outstanding things today: insert and update operations on the database. In particular, this post provides a complete guide to their funky fusion: the upsert operation. Upserts are a…
Writing tests is the easiest way to improve your software's maintainability and reliability. They can communicate the expected behavior of your code with your fellow developers. Yet, I would argue that only organized and easy-to-understand tests are helpful tests. Let's have a look at an often overlooked tool for organizing your tests: Context tags . Let's consider the situation where you write…
Analyzing large amounts of data has become an everyday problem. Oftentimes, the datasets are only available as CSV file, which creates the the question of how you can import them into your Postgres database? The short answer: By using the Postgres' COPY -function. Here's the long answer: Let's imagine you have an Ecto.Schema called Location with the following definition: schema "locations" do…
I decided to play around with OTP recently. It is the core of the Elixir language, but I rarely use everything it has to offer. So, I decided on coding Conway's Game of Life and made every cell its own GenServer . That means that every cell has its own Erlang process . But why? you might ask. Well, because ... why not?! 😄 It took my three attempts to build a correctly running Game of Life since…
Recently, I attended a great talk by the creator of the Nerves library, Frank Hunleth , organized by the wonderful ElixirKenya community. He presented his nerves_livebook -project, which showcased how to setup Livebook on a Nerves device. I found the topic incredibly interesting since it solved an issue I encounter every time I use Nerves. Here's a shortened setup tutorial for how to setup…
I recently got to play around with a Raspberry Pi Zero W and a Waveshare GSM/GPRS/GNSS Hat , a relatively low-cost module (~30USD) for sending text messages, making phone calls, using mobile internet, and tracking your geolocation. In the following, I will walk you through how to set up the hardware and create a simple project for sending out text messages using Nerves and Elixir . The Hardware…
If you want to secure your users' accounts beyond simple username and password authentication, U2F is arguably the most secure multi-factor authentication method you can offer. In order to log in or register, your user needs to authenticate using a physical device like a YubiKey . After entering the username and password, the user needs to authorize the physical device to accept and solve a…
José Valim recently tweeted about the Liveview-Cluster project, which showcased how state can be shared among a global cluster of Elixir nodes. I found this project impressive, because the global state (a simple counter) was shared by 17 machines all around the globe. What I found even more impressive was Fly.io , their server provider. It allowed them to deploy machines in 17 different regions…
What comes to mind when you describe "your product"? Do you think about features built for your customers? How it solves a problem your customers have? Maybe even a logo, a slogan, or its theme color? These aspects describe your product's business side and value proposition . However, they fail to mention the foundation of your product: its software . The reason you might have forgotten about the…
My team at Studitemps and I ran into the problem that we had multiple services, which needed to be served from the same URL. We had one service running the Elixir + Phoenix stack that we considered our “main service”. This service should be accessible under an URL like https://example.com . We also had another service serving our content, which we wanted to integrate into the navigation bar of our…
In a personal project of mine, I regularly fetched data collected by bicycle counting stations scattered around Cologne, Germany, and stored the data in a public GitHub repository . I ran the Python script which was fetching, appending, and uploading the data to GitHub manually for a while, but since I (am lazy and) wanted to always offer the latest data, I thought about how I could automate this…
Here at Studitemps, we have to comply with many rules and regulations that we have to be certain are followed by our software as well. These business requirements have to be poured into production code 1-to-1. Otherwise, we risk losing our students, customers, and at worst, our license. Therefore, we have to make sure that our software behaves in certain ways. We have developed a process of…