So you've got this amazing app idea with a catchy name, a logo (if you're like me), and even a GitHub repo with a commit "First commit what's uppppp" but you're missing something... You just don't know it yet.
* record scratches *
* freeze frame *
"Hi, this is me. You're probably wondering how I ended up here. This is my staging story"
What is staging?
A lot of lone developers either don't know what staging is or even the benefits. I was one of those developers once and I have since seen the light.
Staging in development is creating separate environments for your development and your customers. It actually often extends beyond this (examples to come) and I hope to show you how I stage and what that means for me and my apps.
What are the benefits?
Wicked fast dev times: There is a little bit of work that happens to build the scaffolding that allows you to quickly scale up without worrying or breaking your customers' experience.
A sense of stability: It's much easier to focus on what is coming next in your roadmap instead of what just fell down.
You can fail faster without negative effects on customers.
So where do we start?
In this post I am going to describe how I usually stage my apps and websites that I build independently. The concepts will be easy to see, simple to understand, and will hopefully give you the confidence to do what you want with your staging.
I always have a minimum of two environments. Production and development.
In 99% of my projects both include live services. I am a firm believer that a live service is way better than a mock service if you can have it. Consider something like push notifications. It's really difficult to test those without having an actual production ready push service up and running.
What services do I not have live, and why?
- Mail - The last thing you need is to end up in the junk pile of your customer's email account. In order to avoid being caught as spam, if you can avoid using a live email service in your dev environments, I would.
- Payments - This one should be pretty obvious. When dealing with payments on a dev environment always use the test set up and api keys.
Everything else I have a duplicate project or account for. API's, push notifications, databases, 3rd party services, etc. Check out this screen shot of my firebase projects:
Do you see the pattern?
How do I manage this while developing
Now you've got your services set up, you have a bunch of API keys, how do I manage all of this?
If you are using a build set up like Grunt, Gulp, or Webpack you're in luck. There are plugins for all 3 of these (and then some) that allow you to input data on-build!
If you can take this route I strongly recommend it. Here's why:
- You can keep your keys and secrets in a separate JSON config file that does not go in your repo.
- Easy to update and maintain.
If that isn't an option, you can always swap them out with a variable in your code.
In one of my apps there is even a mechanism in the settings to flip into the developer mode. This sets a local storage variable which on-load is used to set the api keys and api endpoints for the app. This is a great way to have the best of both worlds.
Just be sure to triple check that the code you are deploying is using your production servers. I've almost made the mistake of deploying my app with the dev servers and keys. That would have been very problematic.
I now include some text and things in the logs letting me know that I am obviously in dev mode. I suggest you do the same!
What was that thing about failing fast?
Need to migrate your customer data? Now you can test it beforehand
Want to pilot a feature to some beta testers? Now they can access it without exposing it to the wild
I have gained so much insight from beta testers while still being able to build features and update my existing application. Having a separate environment for that kind of stuff just takes all the stress out of messing up and actually kind of makes you want to mess up because you know you can fix it or scrap it.
Make it reproducible
I'll only touch on this a little bit, because it's an iceberg.
Make your environment reproducible. Know the steps that it takes to tear it down and rebuild it from scratch. Have a database that needs some default data or templates? Keep those on hand. Have a special configuration for push notifications? Write it down and store it somewhere that won't be deleted.
One of the biggest advantages of having multiple environments is that you can, whenever you choose, destroy it and rebuild it. Maybe you need to clear out your test data, try a new push service, reproduce a bug only happening on the latest version of some set of code.
I can not tell you how many times I rebuild my dev environment, it's once or twice a release at the very least.
If you're feeling daring and want to explore the reproducible side of staging and testing, check out Docker. It's fantastic, I hope to be writing some stuff about that soon.
Production Data Security
When you're dealing with customer data you hopefully are very careful with it. But now you've got this other server with much more relaxed rules. The api key lives in a few different places, you might have given out keys to others for help, and you've got a bunch of clutter from your tests.
It sounds like the perfect place to debug something with some production data, right?
Do yourself and your customers a favor, don't ever import your customer data into your development environment unless you are 110% confident that the data is secure and can't be used in any way it shouldn't.
What about cost?
I've narrowed down my work to a few specific services. They are my go to (and not sponsored (but maybe I should be????) unfortunately) and I wouldn't be able to develop so fast without them. One of the best benefits? They're free for low-use like a dev or test environment.
- Heroku - Free for limited use, and only 7$ for a box that's up 24/7. Great for having duplicate projects for dev and production! (https://www.heroku.com)
- Firebase - Not only is the database solution great, but they've moved into push notifications and much more after a big push to integrate with Google. Their pricing is so relaxed that some apps can realistically have a few thousand users a day and not have to pay a penny. (https://firebase.google.com)
- OneSignal - One signal is essentially free up to a million pushes a month. Now I say essentially because they do collect data about your users to use for marketing. This may be an issue in some companies, some it might not. I am not a lawyer and can not comment, please check with your legal team.(https://onesignal.com)
You now have a full stack that can scale with your needs, for pretty much free. You're welcome.
(wow they really should be paying me for that)
Where go to from here?
The sky is the limit! Here's some cool things to try that I've done previously or currently do that works really well with staging:
Throw in another env!
Want to have a special space for your beta testers? Go ahead and throw up an environment for them. Let them know that their accounts won't work unless they're using the beta version of the app and they usually feel more inclined to try crazy things on the app. It's a great way to get some user experience data.
Continuous Integration (CI)
CI is a really fun concept that works great with staging environments. The core idea is that you can push code to your repository and with every push or pull request it will automatically run your tests, if they pass do a build, and post the results online.
Almost every single company uses this in some form to have developer builds (or nightlies, because they're built every day on whatever code is sitting in the repo at that time), betas (somewhat scheduled builds), and production builds (the actual ready-for-release builds).
Get creative in your build set up
I've built build tools that do things like automatically increment the versions, push and tag themselves to GitHub, send slack messages, and even make sounds on an office computer.
Make staging fun, make it worth something.