An app from top to bottom

In this post I will take you through the stack of a real live app I have created, outlining the technology and structural choices I have made.

The reason for writing this is to give myself and others an overview of what it has involved to go from a blank canvas to a complete (minimum viable) SaaS product.

The application in question is OnCall, a small SaaS product I have created in my spare time and launched around a month ago. The app is basic, with the following key areas of functionality.

  • Team management
  • Scheduling of on-call shifts
  • Notifications and reminders
  • Personal schedules and dashboards
  • Account-related stuff (sign in, forgotten password)
  • Subscriptions and payment

Let's start by taking a look the application from a high level to get an idea of the parts.

OnCall overview

Basically the application consists of a public facing website, the application itself, a background worker and some integrations. All of the components rely on the same core library, which I will explain in more detail below.

The public website

This is the website you see at, it's just a simple website with a signup form. The tools and techniques used are the same as the application, so I won't delve into the details here, but just note that the website is run as an Azure Website, whereas the application is run as a web role.

The background worker

Some of the stuff that goes on inside OnCall isn't suitable for being handled by a web application. So things like calculating when to send notifications and reminders, as well as actually sending them is handled by a worker role.

When a user changes notification rules or a schedule, a message is queued to the background worker using Azure ServiceBus. The worker will then calculate whether there are any changes to the upcoming notification schedule for the account.

Communication between roles

Even though these tasks are handled separately the logic exists in the same domain model in the core library that is used by the application.

It wasn't until recently I discovered exactly how powerful Azure WebJobs are. The tasks performed by the background worker could easily be done by WebJobs. I will be looking into making the transition soon as it will bring down both complexity and cost.

The application

The application is where most of the fun stuff happens. It's what you see when visit The basic structure looks something like this.

Application architecture

  1. The user interacts with an AngularJS application
  2. The application is served by an MVC site that has no job except authentication and serving pages
  3. All actual interaction with the application happens through the API
  4. When data is required the API runs read-only queries
  5. The API invokes changes by sending commands
  6. Commands are handled by command handlers which have access to the domain models
  7. All business logic reside in the domain models
  8. The domain model might invoke events upon change
  9. Event handlers act upon these events to perform tasks like sending e-mails etc.

Technology and frameworks used

AngularJS The frontend is a set of AngularJS applications.
Bootstrap The layout is created using the Bootstrap library
MomentJS Used for handling date and time operations
jQuery Required for some UI plugins I use
MVC Pages are served by a basic MVC 5 application
WebAPI Interaction with the server is through a WebAPI 2 API
ASP.NET Identity Handling user authentication
Autofac Dependency injection
Entity Framework EF6 is used for persisting the state of the domain model
Dapper Dapper is used for querying for data
FluentMigrator Used for database migrations
Postmark For reliable e-mail dispatching
Twilio For text messages
Stripe For handling subscriptions and payments
Sentry For error logging
Azure Websites For running the public facing website
Azure Web Roles - For running the multi-tenant web app
Azure Worker Roles - For doing background processing
Azure SQL - For storing all application data
Azure WebJobs - For checking that things are alive and healthy
Azure ServiceBus - For communication between roles
XUnit For unit tests
FakeItEasy For faking and mocking
FluentAssertions For readable assertions in tests
GitHub For code repository
TeamCity For continuous integration
Octopus Deploy For automatic deployment

Thoughts about the stack

The first thing that comes to mind when I see the list above is that it requires a broad set of tools and techniques to create something, even if it is only a simple application.

The stack isn't exactly bleeding edge, the tools I have used are tried and tested. It has allowed me to move quicker during development, and to create something I can trust. It might have limited my opportunities to learn about exciting technology while working with the project, but that wasn't the purpose either, and some of learning efforts have gone into other areas like DDD and CQRS.

When it comes to ORMs I always see myself returning to Dapper. Yes, it does require hand coding your queries, but that also gives you a degree of control. I am confident I have spent much more time tracking down Entity Framework oddities than I have on keeping my Dapper SQL queries up to date.

I have used the TeamCity and Octopus combination since day one. I feel the reward for spending a few hours getting continuous delivery up and running is well worth it, even for smaller projects.

What happens next

I have a few must-dos on my list that I need to get out of the way. First of all, I have some trouble using my continuous delivery setup right now (related to updating a server in Europe while on a mobile broadband connection in the Philippines), I need to sort this out. I also have some work to do on the scheduling functionality which really isn't as good as I want it to be. I would also like to trim the frontend stuff a bit, it is slightly heavy as it is now.

With that out of the way I think it's time to start adding a proper external API, look into creating a mobile application and expanding with a couple of new features.

View Comments