Cloud / Infra providers

Hello,

Im curious about what yall are liking these days for running your Elixir / Phoenix app with a PostgreSQL database. I found these three (gigalixir, fly.io and render.com) and am curious if anyone have any pros and cons about them.

Thanks!

1 Like

I’ve only tried fly.io, and even that not for anything in production, but can attest to its ease of use (and it’s apparently even easier now mix phx.release can create docker images for you: https://twitter.com/chris_mccord/status/1468998944009166849). They’re very responsive on their forum.

2 Likes

Digital Ocean’s App Platform:

  • Runs your Docker image,
  • PostgreSQL,
  • Provides S3-compatible storage if needed,
  • Remote console,
  • Basic graphs for the app and the DB (CPU usage, etc.).

I’m really happy with it. Switched from Render because of the graphs and more responsive remote console - but that was before Render introduced the free tier.

Once you package your app into a Docker image, switching a provider is not that hard.

I was looking to run on render.com for a little project. I was all excited about their free tier but then saw that the DB will stop after 90 days unless you upgrade it to a paid version.

1 Like

The pricing for DO App is awesome. What is the cheapest DB you can add?

I’m using the cheapest one: $15/mo, 1GB mem, 10GB disk.

I am using AWS Lightsail. Managed DB, S3, containers, LB and CDN.
The nice part is that you can move to a more involved setup if you outgrow simple hosting.

I didnt choose DO because their S3(spaces) back then had some troubles.

Some things I remembered from trying those out.

Gigalixir

  1. Uses buildpacks, no Docker support
  2. No Asia region so if your customers are outside the US or EU, good luck with the LiveView latency.
  3. Has managed DBs

Render

  1. Has Docker support, no buildpacks
  2. No Asia region
  3. Has managed DBs

Fly

  1. Has Docker support. But as what others mentioned, deploying Phoenix doesn’t require you to fiddle around with Docker anymore!
  2. Has lots of regions
  3. Chris McCord is working there so that’s a massive win for Phoenix
  4. No managed DBs but they have options to spin a DB up. Although I think you have to manage it yourself, could be wrong now.
2 Likes

Kubernetes on Linode for both the app and the db because nice to not have any vendor lock-in. I played with fly.io and wow its very nice and easy. Much more expensive than linode but I would def consider them for any projects that need low latency across the world.

A couple of quick clarifications on Render:

  1. Our 90-day database free tier is temporary; we’re working on a perpetual free PostgreSQL tier that will replace the current offering.
  2. @stefanchrobot: we have graphs for CPU and memory (and conn counts for Postgres!) What were you missing? Re: the remote console, SSH is launching in early access this week, and native Redis is already in EA.
3 Likes

There was a discussion at the beginning of the year about this (over here), don’t know if you missed it, might find more information for what you’re looking for.

Personally, i still use Scalingo (5 years for any stack, 2 years with Phoenix). Never had any issue (nothing worth mentioning anyway). There not worldwide (well, not like the others, there getting there, you can make a request for access to US based datacenters), so that depends on what you’re looking for i guess. Deployment, managed databases, there close to what Heroku provides, but without a lot of their limitations (they provide a free small database instance to go along a container for testing).

Is that a fairly recent addition? Please correct me if I’m wrong, but it was not there when I was running my app on Render. Overall I was really happy with Render - it works great for Docker-based apps.

One area that I’d like to see an improvement in general is basic log handling: some limited set of features to work with simple logs produced on STDOUT.

We added CPU and memory metrics in 2020!

Re: basic log handling, we now have native integrations with any syslog-compatible log provider including LogDNA and Datadog: Log Streams - Integrate with Third-Party Logging Providers | Render

We’ll build more logging features into Render at some stage, but it’s lower on the priority list given these integrations.

I recently published an article covering the best cloud hosting platforms for Elixir Phoenix on StakNine. I think the best options are Gigalixir, Fly, Render, or Heroku. The criteria included ease of use, so these options provided the easiest path to deploying.

I also published a post for each with steps for deploying a Phoenix app with a Postgres database.

6 Likes

But that’s my actual gripe - for simple setups I don’t want to spend time setting up log forwarding - I just want to see them in the dashboard and have basic tools for working with them.

Agreed, and duly noted.

1 Like

Do you use the managed DB option (the managed DB separate from the DO App experience) or did you add a DB when you were doing through the DO App creation process?

I think I’ve added it during the app setup.

cool - how did you go about telling your elixir / phoenix app about the DB you created?

I got a bit confused because i was following this Deploying with Releases — Phoenix v1.6.4 and saw that they export the db string pretty early in the release process.

mix phx.gen.secret
REALLY_LONG_SECRET
export SECRET_KEY_BASE=REALLY_LONG_SECRET
export DATABASE_URL=ecto://USER:PASS@HOST/database

but if that db string is not available until after the App Platform is created…is a redeploy needed?

My app uses Phoenix 1.6 with esbuild and TailwindCSS. I’m building it with Docker, relying on runtime.exs to handle the config and I pass everything via ENV vars.

Dockerfile:

FROM hexpm/elixir:1.12.2-erlang-23.3.4.5-alpine-3.13.5 AS builder

# Install build tools.
RUN apk add --no-cache build-base nodejs=14.18.1-r0 npm=14.18.1-r0 git=2.30.2-r0

# Prepare build directory.
WORKDIR /app

# Copy the sources.
COPY . ./

# Install Hex and Rebar.
RUN mix local.hex --force && \
    mix local.rebar --force

# Build in prod env.
ENV MIX_ENV=prod

# Get and build dependencies.
RUN mix deps.get && \
    mix deps.compile

# Build assets.
RUN npm --prefix assets install && \
    mix assets.build

# Assemble the release.
RUN mix release

# Prepare the release image.
FROM alpine:3.13.5 AS release

# Install dependencies:
# - Erlang requires ncurses-libs
# - the :ssl module dynamically links to openssl
RUN apk add --no-cache openssl ncurses-libs

WORKDIR /app
COPY --from=builder --chown=nobody:nobody /app/_build/prod/rel/app ./

# Use the user with minimal permissions.
RUN chown -R nobody:nobody /app
USER nobody:nobody
ENV HOME=/app

CMD ["sh", "-c", "bin/app eval MyApp.Release.migrate && bin/app start"]

config/runtime.exs:

if config_env() == :prod do
  config :my_app, MyApp.Repo,
    ssl: true,
    url: System.fetch_env!("DATABASE_URL"),
    pool_size: System.fetch_env!("DATABASE_POOL_SIZE") |> String.to_integer()
end

In the app’s config, the DATABASE_URL environmental variable is set to ${db.DATABASE_URL}. Not sure what the syntax is, but it somehow references the managed DB and it just works. The database page has a “Connection details” dialog where you can show the “Connection string” if you need to set it explicitly.

Generally speaking, when building the Docker image, I only set ENV variables that are strictly necessary (MIX_ENV, stuff like GIT_SHA) because they are baked into the image. Changing the values requires rebuilding the image. The rest is read at runtime, so that I can change the config by just restarting the app.

At least that’s the theory. Some platforms will export the ENV variables during both the build time and runtime. Some platforms won’t allow me to restart the app without redeploying. But I like to keep it clean and separated - it will definitely help if I want to move to a different IaaS.

1 Like