Fridaybuilds is mainly targeted towards solo developers and small startups who build fullstack or backend applications. We take away the need to manage a server manually, so you can focus on the actual products you are building and not the deployment process or any other part of DevOps.
Heroku is a great platform, but it can get expensive quickly. We aim to provide a more cost-effective solution, which gives you more control over the resources your app uses, while at the same time being easy, useful and reliable.
Our aim when creating this platform is to make it so useful and fair-priced, that it doesn't make sense to go self-hosted unless you actually want to.
However, self-hosting is not that difficult anymore and it can be a great option for a lot of use cases. There are amazing open-source tools (such as Dokku), which make the process of deploying apps to a VPS as easy as deploying to Heroku (or Fridaybuilds!). If keeping costs to the absolute minimum is your goal, then self-hosting is the way to go.
We hope you can still see the value in our platform, regardless of which option you go for. Keep reading to learn more about how everything we do works!
On the backbone of our systems lives Kubernetes. Your apps, services and command/shell runners, all spin up new Kubernetes pods.
Deployments are as easy as pushing your latest code to a git repository we provide for your app. Whenever you push new code to that repository, we automate all the necessary steps to end up with a new docker image created for your app. This image is then spun up in a new Docker container and traffic is routed to it.
If there are bumps on the road, you can inspect the logs of the deployment process to see what went wrong and try again.
You can deploy any app that runs with: Ruby, Python, PHP, NodeJS, .NET, Go, Java. More languages will be added soon.
Language support is based on Heroku Buildpacks provided via Gliderlabs Herokuish
Buildpacks are scripts that run during the build process of your app. They are responsible for detecting the type of your app, installing dependencies and preparing the app for deployment. You don't need to worry about them, as they are automatically selected based on your app's codebase.
Setting a custom buildpack is supported, but not yet implemented on the web interface. If your app requires more than one buildpacks to work (usually the deployment log will show a relevant note in such cases), please contact us and we will configure your app manually.
Resource bundles define the cpu and memory (RAM) allocated for a container. These bundles are the main factor that incurs charges on your account. A bundle can be set for anything that spawns containers, like processes, services, runners (interactive shell sessions, one-off commands)
The bundles are very customizable and should fit any need. They range from 0.1 to 4 CPUs and 128MB to 8GB of memory. These values define the upper limit of the resources available to the containers they attach to.
Bundle prices are the same no matter what type of container they attach to. See pricing
Apps are the main entities in the system. An app contains your code, environment configuration and has connected domains, services, activities, etc.
Every app has a unique identifier called a slug. An app's slug identifies the app in the system and is used in the default app URL, provided for every app. For now, you can only set it upon creation and it cannot be changed later.
Services are additional components that connect to/communicate with your app. For example, you can add a database service or a redis service to your apps.
In the context of FridayBuilds, the difference between services and processes is that processes run commands that exist in your codebase, while services typically spin up containers that execute some other predefined code (e.g. postgres). You might have seen other providers call everything a service. For example, you might have seen a `web` process being called a `web service` or a background process being called a `worker service`.
Services have storage restrictions. Learn more
The version of a service is automatically set to the latest stable version at the time you add the service. Version upgrades are not yet supported, but will be added in the future. Backups for databases are not yet implemented, but planned with high priority.
Postgres is a production-ready relational database service. When you add a Postgres service to your app, it will automatically create a new Postgres database for you. A `DATABASE_URL` config variable will be set for your app, which you can use to connect to the database from your app's processes. This URL is not meant to be used outside your app's processes, as it is not exposed to the internet.
MySQL is a production-ready relational database service. When you add a MySQL service to your app, it will automatically create a new MySQL database for you. A `DATABASE_URL` config variable will be set for your app, which you can use to connect to the database from your app's processes. This URL is not meant to be used outside your app's processes, as it is not exposed to the internet.
Redis is a production-ready key-value store service. When you add a Redis service to your app, it will automatically create a new Redis instance for you. A `REDIS_URL` config variable will be set for your app, which you can use to connect to the Redis instance from your app's processes. This URL is not meant to be used outside your app's processes, as it is not exposed to the internet.
An app usually has multiple processes running to fulfill its purpose and functionality. For example, every web app has a process named web; it's the only process that we route external HTTP requests to. An additional process for example could be a background worker.
You can define processes for your app by adding a file named `Procfile` to your app's root directory. When a Procfile is missing, we will attempt to detect the default process for your app, based on your repository code.
A Procfile is a file that defines the desired processes for your app. It contains the name and the run command for each process. For example, a Procfile for a Ruby on Rails app might look like this:
# Procfile
web: bundle exec rails server
worker: bundle exec sidekiq -e production
release: bundle exec rails db:migrate
The web process is the only one that can receive HTTP requests from the outside world (i.e. exposed to the internet). Requests pointing to your app's domains will be routed to this process.
The release process is a special command that only runs after each successful deployment.
Apart from web and release, you can use any name you want for your processes.
Every app has a unique URL, but you can also connect your own domains.
Newly added domains will be automatically configured with SSL certificates (provided by Letsencrypt), once they resolve correctly. Domains that are not secured with SSL will show a relevant icon next to their name.
You can add a custom domain to your app by going to the app's settings page and clicking on the "Add Domain" button. Once the domain is added, find it in the list of your app's domains, click on the icon and select "View instructions" to see how to set up the DNS records for your domain.
Apps can have environment variables set. These variables can be used to store sensitive information, such as API keys, database connection strings, etc. They can be set in the app's settings page.
You can remotely run commands in the context of your app.
There are two types of remote commands: one-off commands and interactive terminals.
One-off commands are useful for running migrations, seeding the database, or any other command that you need to run in the context of your app. You can run a one-off command by going to the app's settings page. On the "Remote Commands" section you can type in your command and click the "Run" button to execute.
One-off commands will be executed in a new container, which will be automatically removed after the command finishes running.
You can also start an interactive terminal session in the context of your app. This is useful for debugging or running commands that require user input. You can run an interactive terminal by going to the app's settings page and clicking on the "Open a shell terminal" button.
Interactive terminals will be executed in a new container, which will NOT be automatically stopped/removed. You have to make sure to properly exit or terminate the spawned terminal. You can find and manage running terminals on your app's "Resources" page.
You can allocate resources required by your app's processes or services vertically (more CPU and/or memory). App processes can also scale horizontally (more instances of a process, using the selected resource bundle). For now, all instances are limited to the same region. We do however have planned features for spreading instances across multiple regions.
Apps do not persist data between restarts or deployments. This means that every time you deploy a new version of your app, or your app is restarted, any data that was written to the filesystem after the last deployment will be lost. If your app has file storage requirements, you will need to resort to a third-party solution. Such solutions include AWS S3, Digital Ocean Spaces and others.
While apps themselves do not have access to persistent storage, services do. Your database data will persist even if your app, database service container, or the entire server restarts. However the storage options are currently limited and priced based on reserved storage size. Keep in mind that occupying all reserved storage, will stop the service container and your app won't be able to use that service. Storage options and prices will be re-evaluated at a later stage, as we get a better idea of the use and requirements of FridayBuilds apps.
If the current storage limitations do not fit your use case, you should probably consider using a third-party database service provider. You can always connect third-party services by setting the appropriate config variables on your app (eg. DATABASE_URL)
Every time you deploy a new version of your app, a new docker image is created. This image is then used to spin up new containers. The size of the image is the sum of the sizes of all the files in your app's codebase, the size of the underlying docker image and the size of the dependencies your app uses. This image currently has a limit of 2GB. If your app exceeds this limit, the deployment will fail with a message explaining the issue.
You can view your latest deployed image size in your app's settings page.
To reduce your app's image size, you can:
If you need a larger limit, please contact us with a brief explanation of your use case and we will try to offer an appropriate solution.
Every app has logs for its processes, which you can view in the app's logs page. Logs are kept for a limited time and are not persisted between container restarts.
Log persistence/draining is not yet supported, but it is planned for the future.
You can view metrics for your app's containers in the app's stats page on a 30-minute rolling window, which updates every 30 seconds. The metrics include CPU usage, memory usage, network traffic and disk IO.
Your app's monthly outgoing traffic is metered and is shown in the app's stats page. Outgoing traffic is calculated across all your app's containers and aggregated after compensating for the traffic that goes to the internal network.
Apps that exceed their traffic quota will be stopped. An email notification will be sent when an app's traffic quota reaches 80%. If you expect to exceed your current quota please contact us in time, so we can work out a traffic plan for your app(s) and avoid your app getting stopped.
Incoming traffic is not metered.
At the beginning of each month you will be charged for any expenses that have been incurred during the previous month. Compute resources charges only incur when the resources (eg. app process, service, interactive terminal) are running. Charges are prorated to the second. You can view a detailed analysis of your container charges in the billing section of your account.
Storage charges are tiered in 128MB steps of reserved storage. The first 128MB for each service is free. Then, we charge EUR 0.1 for each 128MB of additional storage reserved each month. For example, if you select a 256MB storage option for a service, you will be charged EUR 0.1 each month, regardless of when you started using this storage. If you reserve 512MB of storage, you will be charged EUR 0.3 each month, and so on.
You can see your current balance in the billing overview page. Your balance is the sum of all your transactions (charges, payments, credits). You can see a detailed list of all your account transactions in the transactions history page.
Your refunds are listed in the transactions history page. However, they do not affect your account balance. This is because a refund can be of two types: credit refund or money refund. A money refund will return the amount to your original payment method (and so does not affect your account balance), while a credit refund will add a separate credit record to your account. This credit record is what actually affects your account balance.
For example, issuing a credit refund of 10$ will show one credit record of 10$ and one refund record of 10$. However your active balance will only increase by 10$.
In the case of a money refund of 10$, you will only see one refund record of 10$ and your active balance will not change, since the amount will be returned to your original payment method (i.e. your credit/debit card).
Credits added to your account will automatically be redeemed by applying a discount on your next invoice. Credits may have an expiration date; the ones that expire the soonest are prioritized when applying discounts.
When a credit record is applied (either in full or partially), you will see a new transaction record in the transactions history page with the used amount. The original credit record will not be deleted, but will show the remaining amount.