• This repository has been archived on 23/Oct/2021
  • Stars
    star
    155
  • Rank 239,960 (Top 5 %)
  • Language
  • Created over 8 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Selling points for Elixir / Phoenix

Why Elixir and Phoenix?

Suppose Ruby on Rails is your standard back end technology. Why might one choose the Elixir language and/or the Phoenix framework instead?

One reason is that the software industry is moving to functional, concurrency-friendly languages. You need to be competent with languages like this, and Elixir has some unique properties that make it great for the web and flexible for other use cases.

Pros

Reliability

First off: yes, Elixir is a fairly new language. That might make you think it's not reliable. But Elixir is mostly a friendly interface to the Erlang virtual machine.

Erlang has been used since the 80s to build some of the most reliable systems in the world. It was developed to run telephone systems. People die if the telephone doesn't work.

So the creators of Erlang developed a language and baked into it strategies for running a complex system with almost no downtime. Those strategies include having multiple levels of "supervising" processes in a system to reboot parts that have errors. They were doing microservices before microservices were cool.

And because they were running their code on many telephone switches, they also invented a great model for running code concurrently (see below).

New as it is, Elixir harnesses all the power of Erlang and provides friendly syntax and tools for using it.

Concurrency

Computer CPUs are no longer getting dramatically faster each year. Instead, we get machines with more cores. This lets our code run faster, but only if it can run concurrently - meaning, different bits of code run simultaneously on different cores.

The main problem with concurrent code is having two pieces of code mess with the same data at the same time, creating unexpected results. Object-oriented languages like Ruby don't provide great tools for avoiding such problems. But functional languages, like Elixir, do. Writing concurrent code in Elixir is extremely easy, and it's nearly impossible to accidentally interfere with other code that's running at the time.

In Ruby, we never ask "can I create another object?" Everything in Ruby is an object, and objects are cheap. We create as many as we want.

In Elixir, processes are like objects - we can create thousands of them, all running concurrently, and never worry about it. This ability simplifies a lot of the problems we normally have in Ruby.

Simplicity

When we write Rails applications, our Rails app depends on a lot of other pieces.

We can only handle one web request at a time with a Rails app, and we can't spin up new processes as needed, so we have to use tools to spawn multiple application servers up front and put a web server like Nginx in front of them to hand off requests.

We can't do slow background tasks without blocking our web requests, so we have to add Redis and Resque to take care of running background jobs.

We can't use a precious process to maintain a websocket connection with a user, so we have to add Pusher to get realtime functionality.

We can't keep a big Ruby process running all the time to do scheduled tasks, so we add a dependency on cron.

We have no built-in Ruby tool for managing multiple parts of a running system, so we resort to tools like foreman and god to start and monitor them.

In Elixir, we can spin up a nearly limitless number of processes as needed, so we can (in theory) forego all those tools.

Elixir code is also simpler to understand than object-oriented code because it has explicitness as a value.

"Functional programming is associated with concurrency but it was not by design. It just happens that, by making the complex parts of our system explicit, solving more complicated issues like concurrency becomes much simpler." - Jose Valim

Performance

The Phoenix web framework is much more performant than Rails. One benchmark showed Phoenix handling more than 10x the requests in a given period. Phoenix was also much more consistent under load - Rails was more prone to have some requests bog down. This can cause a "chain reaction", because Rails apps are configured with a fixed number of application processes, so if some of them are slow, it can mean that others have to wait in line, which dramatically increases response times.

What's more, Phoenix apps without caching drastically outperform Rails apps with caching. This is important because caching is notorious for being a source of complexity and bugs, and because caching can't be used for moment-by-moment, personalized content like that offered by Bleacher Report, which shows users news and tweets about the teams they're interested in and handles 250k concurrent users. According to a talk their developers gave, they went from over 100 AWS servers to 5, with CPU usage rarely going above 10%, and saw a 10x performance improvement over their Rails app.

One of the ways Phoenix outperforms Rails is in faster, memory-efficient template rendering, based on how the Erlang VM handles string IO. An Erlang web framework describes it this way:

Erlang Respects Your RAM! Erlang is different from other platforms because when rendering a server-side template, it doesn't create a separate copy of a web page in memory for each connected client. Instead, it constructs pointers to the same pieces of immutable memory across multiple requests. So if two people request two different profile pages at the same time, they're actually sent the same chunks of memory for the header, footer, and other shared template snippets. The result is a server that can construct complex, uncached web pages for hundreds of users per second without breaking a sweat. With Erlang, you can run a website on a fraction of the hardware that Ruby and the JVM require, saving you money and operational headaches.

I've written about this in more detail on the BNR blog.

There are a growing number of companies using Elixir - eg, Pinterest says:

So, we like Elixir and have seen some pretty big wins with it. The system that manages rate limits for both the Pinterest API and Ads API is built in Elixir. Its 50 percent response time is around 500 microseconds with a 90 percent response time of 800 microseconds. Yes, microseconds. We’ve also seen an improvement in code clarity. We’re converting our notifications system from Java to Elixir. The Java version used an Actor system and weighed in at around 10,000 lines of code. The new Elixir system has shrunk this to around 1000 lines. The Elixir based system is also faster and more consistent than the Java one and runs on half the number of servers.

Scalability

The Erlang VM's model of concurrency is great for multi-core CPUs, but it was created before they existed. Its original purpose was to support concurrency and fault-tolerance via the use of many different machines.

This makes it an excellent tool for building systems that can handle more load by simply adding more server machines.

As the docs for an Erlang web server put it:

At the time of writing there are application servers written in Erlang that can handle more than two million connections on a single server in a real production application, with spare memory and CPU!

The Web is concurrent, and Erlang is a language designed for concurrency, so it is a perfect match.

Of course, various platforms need to scale beyond a few million connections. This is where Erlang's built-in distribution mechanisms come in. If one server isn't enough, add more! Erlang allows you to use the same code for talking to local processes or to processes in other parts of your cluster, which means you can scale very quickly if the need arises.

Flexibility

Using Phoenix and Elixir opens the door to building applications that just aren't realistic for Ruby and Rails.

The Phoenix framework has first-class support for realtime communication via websockets (or polling, as a fallback). In benchmarks, the creators have been able to serve 2 million simultaneously-connected clients! Additionally, they already have native channel clients for iOS, Android, and C# (Windows devices). With that kind of support, you can confidently build servers to support chat, networked games, and more.

Elixir is also a good candidate for running embedded code via Nerves. This is not possible with standard Ruby (although it would be with mruby).

Correctness

Rails' ActiveRecord encourages developers to do all data validation in application code. However, validations that depend on the state of the database can only be reliably done by the database, using constraints or locks. This includes things like:

  • Does any user have this username right now? (uniqueness constraint)
  • Does post 5 exist still right now, before I comment on it? (foreign key constraint)
  • Does this user's account have enough money to cover this purchase right now? (CHECK constraint)
  • Is this rental property reserved for June 8 right now? (EXCLUDE constraint on date ranges)

It's possible to use such constraints with a Rails application, but it's not typical to do so, and the tools don't encourage it.

Elixir's Ecto database tool embraces database constraints, with built-in support for adding them, catching constraint violations, and turning them back into friendly user-facing error messages. In fact, you have to go out of your way to do something like a uniqueness check in application code.

Cons

  • There are fewer libraries in Elixir than in Ruby, so there are more times when you'd have to write something yourself. However:
    • You can use the many existing Erlang libraries
    • New Elixir libraries are being added quickly
    • Any remaining gaps are a chance to to "make a name for yourself" in Elixir by creating a great open source tool
  • There are also fewer services for Elixir for things like error monitoring. However, this is also changing (see Honeybadger), and the Erlang VM provides much better tools by itself than Ruby does. (2015 talk on this.)
  • For consultancies, it may be harder to sell clients on Elixir, given that it's currently obscure - not in the top 50 TIOBE index. However:

Indicators of a Good Fit

Really, any greenfield project that is a good fit for Rails is something that could be done in Phoenix.

But you'd have an especially strong case if the project involves any or multiple of the following:

  • System expecting high traffic or requiring very fast / consistent response times
  • Minimal downtime is crucial
  • Realtime updates (eg, stock ticker)
  • Bidirectional realtime communication with websockets (eg, chat, games)

More Repositories

1

expandable-recycler-view

[DEPRECATED]
Java
1,215
star
2

Freddy

A reusable framework for parsing JSON in Swift.
Swift
1,090
star
3

CoreDataStack

The Big Nerd Ranch Core Data Stack
Swift
562
star
4

Deferred

Work with values that haven't been determined yet.
Swift
421
star
5

developing-alexa-skills-solutions

JavaScript
232
star
6

Typesetter

Android tool to help display changes to text positioning.
Java
150
star
7

iOS7Demos

Some short demos of new stuff in iOS 7
Objective-C
145
star
8

BNRDynamicTypeManager

Objective-C
127
star
9

android-bluetooth-testbed

Provides a Server and Client example for understanding Bluetooth Low Energy on Android
Java
97
star
10

music-frequency-d3

A music frequency visualizer using D3.js
JavaScript
93
star
11

rust-ios-app-part-1

Let's Build an iOS App in Rust, part 1
Swift
81
star
12

iOS8Demos

iOS 8 release day demonstrations
Objective-C
77
star
13

AndroidCourseResources

Resources for our Android Bootcamp.
Java
75
star
14

stockwatcher

stockwatcher, a modern android development stack showcase
Java
62
star
15

alexa-airportinfo

Node.js src for the article "Developing Alexa Skills Locally with Node.js"
JavaScript
61
star
16

bnns-cocoa-example

An example of a neural network trained by tensorflow and executed using BNNS
Objective-C
59
star
17

type-erasure-playgrounds

Code to accompany Swift Symposium Talk - https://www.youtube.com/watch?v=d_FJHBl5ohU
Swift
56
star
18

Result

Small Swift library for Result type
Swift
47
star
19

android-listview-custom-view

Example of using a custom view subclass with ListView and a custom Adapter
Java
45
star
20

linette

Custom lint checks for Android development.
Java
42
star
21

rust-ios-app-part-3

Let's Build an iOS App in Rust, part 3
Swift
31
star
22

iOS3eSolutions

Solutions to iOS Programming: The Big Nerd Ranch Guide, 3rd Edition.
Objective-C
31
star
23

doze-logger

Simple app thrown together to help demonstrate the effects of doze mode on your background schedulers.
Java
30
star
24

ScriptableTextEditor

A simple Cocoa text editor that demonstrates creating a plugin system in Python.
Objective-C
29
star
25

DeferredTCPSocket

DeferredTCPSocket is a Swift framework for asynchronous TCP networking.
Swift
28
star
26

macOS-bootstrap

A bootstrap script for configuring machine to develop iOS, tvOS, and macOS apps
Shell
25
star
27

BNR-blog-cameraxMlkit

Sample project associated with blog post on using Firebase MLKit with CameraX.
Kotlin
21
star
28

blog-ios-xcui-todo

Demonstrates using Xcode 7's new UI testing support
Swift
20
star
29

BNRun-SiriKit-Sample

Sample code for the SiriKit blog post
Swift
19
star
30

Roger

Roger is jolly. By Franklin.
Objective-C
18
star
31

controllers-for-tvOS

Sample app for tvOS that reads game controllers
Swift
18
star
32

jenkins-android-signing

[DEPRECATED] Jenkins Plugin for signing Android APKs
Java
18
star
33

alexa-account-linking-service

Code example for the Oauth account linking example for an alexa skills
JavaScript
17
star
34

tensorflow-cocoa-example

Using tensorflow inside a desktop Cocoa application
Python
17
star
35

ViewRotationTest

A demonstration of various techniques for view rotation in Cocoa Touch.
Objective-C
17
star
36

BlappyFird

Demo clone of a popular game
Swift
16
star
37

rust-ios-app-part-2

Let's Build an iOS App in Rust, part 2
Swift
12
star
38

rust-ios-app-part-4

Let's Build an iOS App in Rust, part 4
Rust
12
star
39

react-testing-workshop

Starter Code for BNR React Testing Workshop
JavaScript
11
star
40

BNRXIBCell

A UITableViewCell subclass, intended to be subclassed, to forward action messages from cell subviews to a controller.
Objective-C
11
star
41

opencv-cocoa-example

An example of using OpenCV in a Cocoa application
Objective-C++
10
star
42

BNR-blog-motionlayout

Sample project associated with blog post on using MotionLayout and MotionEditor.
Kotlin
9
star
43

semaphorejs

A functional-style Semaphore for managing concurrent access to a resource. For JavaScript.
JavaScript
9
star
44

RanchWeather

A demo app written in Swift 3 to demonstrate different code patterns.
Swift
9
star
45

android-securebank

Code example companion for the DevNexus talk: "Keeping Android Secrets Secure with Fingerprint Authentication and the Keystore"
Java
8
star
46

ember-engine-example

Ember-Engine Example: Large Company Site from Blogpost
JavaScript
8
star
47

dexie-fulltextsearch

Full text search for IndexedDB databases, powered by Dexie.
JavaScript
8
star
48

id3-meta

A metadata parser for ID3v2 formatted MP3s, in JavaScript.
JavaScript
8
star
49

SyncAdapterDemo

Experiment with android sync adapters. Getting them to work with a remote rails server to sync book error data.
Java
8
star
50

iOS-Responsive-UI-Sample

3 examples examining modern techniques for making iOS app UI accessible and responsive.
Swift
7
star
51

OpenParentApplicationDemo

Demo of openParentApplication method of WatchKit
Swift
7
star
52

doktor-demo

A simple Ktor demo app. Write Kotlin on the server.
Kotlin
7
star
53

BNRLoupe

A magnifying loupe for images that displays one-for-one pixel information for the point under the finger.
Objective-C
7
star
54

permission-manager

Easily and seamlessly ask for Android runtime permissions.
Java
7
star
55

alexa-cakebaker

JavaScript
7
star
56

cocoa-conf-stack-views

@cbkeur's CocoaConf talk on UIStackViews
Swift
6
star
57

character-data-api

Kotlin Ktor backend for the Samodelkin Android Client
Kotlin
6
star
58

meta_elixir

Elixir
5
star
59

cleaning-up-messy-chaining-code-in-swift

Swift
5
star
60

ShindigSheriff

Event Manager Manager, Mr. Manager
Ruby
5
star
61

auto-layout-mastery-conference-talk-2016

Step's Auto Layout Mastery talk about Priorities
Swift
4
star
62

upfront

Go
4
star
63

ottergram-solutions

Sample of how we could organize solutions for the 4 apps in the frontend book.
4
star
64

FocusWheel

A tvOS app for a two-part Big Nerd Ranch Blog Post on collection view layouts and the focus engine
Swift
4
star
65

Github-Issues-Reader

A super cool app for reading github issues that definitely doesn't already exist
Swift
3
star
66

cocoa-layout-instrument-demo

Sample files to accompany a blog post on the Cocoa Layout Instrument.
Swift
3
star
67

BNR-react-native-style-queries

Declarative responsive design for React Native.
JavaScript
3
star
68

bootstrap

Ruby
3
star
69

SocialDistancingSimulator

A SpriteKit-based social distancing simulator
Swift
3
star
70

auto-layout-priorities-2016

Demo project that accompanies Auto Layout Mastery Conference Talk on priorities from Step Christopher
Swift
3
star
71

alfred_reflecticle_extension

Ruby
2
star
72

KotlinConf2023-TestRefactor

Kotlin 2023 Testing Workshop Template
Kotlin
2
star
73

tacostand

A sample project for practice using Rails applications
Ruby
2
star
74

authorizing-jsonapi-resources

A tutorial for protecting private resources in JSONAPI::Resources.
Ruby
2
star
75

BNR-blog-React-to-Vue-react-simple

React project for comparison to Vue for blog entry
JavaScript
2
star
76

vapor-testing-example

Demonstrates testing techniques in the Vapor framework
Swift
2
star
77

bnr-webhooks

Big Nerd Ranch's webhook layer for inter-service communication.
Ruby
2
star
78

cardo

DSL for creating recurring Pivotal Tracker stories
Ruby
2
star
79

ember-engine-external-admin

Ember-Engine Example: External Admin
JavaScript
2
star
80

html5-course-ajax-dummy

Just a dummy AJAX endpoint for the HTML5 course.
Ruby
2
star
81

CrashTest

UIKit Dynamics Playground
Objective-C
2
star
82

KotlinConf2023-ContextReceivers

The supporting code for Bryan Sills's talk titled "Introduction To Context Receivers" at KotlinConf 2023
Kotlin
2
star
83

constraints_experiments

Some experiments for a blog post
Elixir
2
star
84

BNR-graphql-java-samples

Holds some meaningful examples of building GraphQL API's in Java.
Java
2
star
85

nybblr-javascript-book-walkthrough

My run through of the frontend dev book.
JavaScript
2
star
86

AtomicSwift

Objective-C
1
star
87

BNR-blog-React-to-Vue-vue-simple

Vue project for comparison to React for blog entry
Vue
1
star
88

gatsby-twenties-tribute

A tribute page to the twenties built with Gatsby.js
CSS
1
star
89

ml-boston-pricer

A repo for hosting the demo project for BNR's Core ML blog post.
Swift
1
star
90

service-object-testing-example

Java
1
star
91

devnulldb

:trollface: MySQL server
JavaScript
1
star
92

clash_of_the_coders

Site for Clash of the Coders scoreboard
Ruby
1
star
93

omniauth-stable

Omniauth Strategy for Stable
Ruby
1
star
94

KotlinConf2023-ComposeForDesktop

The supporting code for Bryan Sills's codelab titled "Compose For Desktop" at KotlinConf 2023
Kotlin
1
star
95

RubyCourseResources

Files and helpful info associated with the Ruby portion of our Beginning Ruby on Rails Bootcamp.
1
star
96

carkeeper

Sample code accompanying @lyricsboy's talk "Applying the Single Responsibility Principle in iOS"
Objective-C
1
star
97

ios-ci-example

Example Distribution for the Travis CI Integration of a sample app
Objective-C
1
star
98

TableCollectionView

Handful of classes that make it easier to use a Collection View as a replacement for a Table View
1
star
99

iOS-Win8-Seminar-Public

Files for use in the exercises of the "Windows Store Development for iOS Developers" seminar.
1
star
100

iOSCourseResources

1
star