Haskell in Production
source link: https://www.tuicool.com/articles/Y3YNjeR
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
During the past year, my team has been building production services using Haskell. It’s been quite a journey. None of us had written production code using Haskell before. We were all familiar with the language and excited to get to assess it in production. Because that’s really what we’ve been doing; seeing if Haskell is a good fit for us in order to deliver quickly and with great quality.
tl;dr
Haskell is great for business and great in production. Attracting talent has been a joy, people are excited to work in Haskell. The libraries we’ve needed exist in battle-tested form on Hackage/Stackage. The code we’ve produced has made it easy to onboard new folks.
The longer version
Knowing exactly how we wanted to write production services using this language was not as straightforward.
We tried a lot of different patterns - readers, handlers, MTL, and tagless final. You’ve surely heard of some of these, and they all have their own pros and cons. So, which one should you choose?
That is why I’ve written this article series, to help you get a good sense of how production Haskell is written at a company like Klarna and what to avoid along the road.
Existing parts in this series
- Part 0: Introduction (this page!)
- Part 1: Making components testable
This section will be updated as more articles are published.
Companion repo
For this series you can find the code that goes along with each part in the haskell-in-production repo on GitHub.
Concerns when writing a production service
We have a couple of concerns that we would have no-matter which language we’re writing our service in.
- Multiple environments and regions
- Testability
- Performance & scalability
- Maintainability, logging, and traceability
When you’re coming from object-oriented programming, you usually think of these things in order to facilitate the above:
- Dependency injection
- Mocking
In functional programming, we have techniques to cover both. Whereas these frameworks often opt for meta-programming level annotations and reflection - FP leverages language level features. This allows you to stay purely within the language.
Below, I’ll elaborate some more on the requirements posited above. If you want to skip ahead to how we’ll solve these concerns - please seepart 2 of this article series.
Multiple environments
Klarna provides multiple environments for its services, we have (at least) the following:
-
Staging
This environment doesn’t really have an SLA, but you should expect other teams to write end-to-end tests against services that you deploy here.
-
Performance
This environment is used in order to do load testing, or stress tests on your service
-
Production
Perhaps obvious, but this is the service that actually serves live traffic. Depending on which team you’re in you can have very strict requirements in your SLA, e.g. 5 nines up-time, latency requirements etc
Multiple Regions
Some services are served in both the EU and US regions. For services in the US, we cannot share any data to the EU. For the services that my teams write, we have certain integrations in the EU - Swedish national bank, the European Central bank. These of course should not be made available in the US.
Testability
We need to be able to test different components in isolation. Some of these components are pure or can be tested in a pure manner - if we mock out certain dependencies.
Maintainability
What is different here than for a regular service? Well, for starters it is possible to write some really obscure code using a combination of Haskell and compiler extensions.
As technical lead for our teams writing Haskell applications, it is my job to make sure that others are productive. Thus, this article will emphasize writing easy to grok, maintainable code.
Proposed solution
We will write a configurable, testable service that deploys to a cloud provider. The application will be shipped in a docker image and deployable as such.
Next part Designing Testable Components
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK