In our Haskell in Production series, we interview developers and technical leaders from companies that use Haskell for real-world tasks. We cover benefits, downsides, common pitfalls, and tips for building useful Haskell products. Today’s guest is Flavio Corpa, the Senior Software Engineer of Scrive – a company providing electronic signature services and eID solutions.

Technical Stack & Architecture
What was the architecture of Scrive like when Haskell was first introduced? What kind of problems was it intended to solve at that point?
One of the founders, Gracjan Polak, was a functional programming enthusiast. He started programming Scrive using Haskell for the backend from the very beginning.
Which parts of your system are written in Haskell today, and where did you deliberately choose not to use it?
Most of the electronic signature and eID backend is written in Haskell, with a notable exception in the final PDF handling logic, where the iText library is used via Kotlin.
Were there any unexpected advantages or friction points when using Haskell in a highly regulated domain, with legal traceability and audit requirements?
In audits, we have to respond to questions like: “Which static code analysis are you using?”. It is a bit hard to explain why Haskell does not have any.
Do you use AI for Haskell development? Could you share your experience with it? Is it helpful? How do you think the rapid growth of programming AI will affect the future of Haskell?
Yes the company encourages us to use AI in our Haskell development and provides us with Github Copilot licenses, I have been using it recently but also besides my job I’ve been using tools like Cursor and Windsurf for developing with TypeScript and Svelte and I have to say I feel like the support of LLMs for Haskell is quite limited in my view. This was to be expected because of the reduced sample size of the dataset we have compared to other mainstream languages, but I really hope they will become smarter in the future and aid us even in such complex languages as Haskell!
What build and deployment tools do you use in dev environments and for CI/CD?
We have a mix of Docker and Nix company-wise, but mostly our CI/CD is Docker with Kubernetes, and it is working fine for us, but I would say I feel it is a bit slower than it should be. Definitely, there’s room for improvement there.
Scale, Interfacing & Observability
Scrive integrates with many external partners — from banks to government entities. How has Haskell held up when dealing with complex, real-world API interactions? Context: Digging into serialization, FFI, latency, and error resilience.
There was a point where we had to hand-roll a SOAP client in Haskell for an external integration :) But overall, we mostly find what we need in the ecosystem - sometimes resorting to maintaining some of the packages (for example, hpqtypes).
How do you handle observability in your Haskell services — logging, tracing, metrics? Was this an area where you had to build extra tooling or abstractions?
We use Prometheus through the prometheus-haskell suite of packages. Logging is done with our own open-source toolkit: https://github.com/scrive/log. Metrics are produced with a fork of the tracing library and sent to Grafana Tempo.
Haskell in Production: Lessons and Tactics
What are some hard-earned lessons from maintaining Haskell in production at scale? Any anti-patterns you’d warn others to avoid?
Functions that acquire locks on the database can be at the root of production issues if they are not well-understood by developers, and this starts with the name. A function called withLockedDocument will be used more carefully than a function simply called withDocument.* Trying to fit several entities that have admittedly similar shapes, but wildly different life cycles, into one type will come to haunt you sooner than you think. You can resort to a number of tricks to express two different types of users in the same data type, but this will put a burden on your code. Write a new data type; it’s free. In some parts of the codebase, we are using effectful, and we are very happy with it, btw ;)
How do you onboard new engineers who aren’t experienced in Haskell? Has this influenced how you write or structure code internally?
Mob and pair programming are a huge thing within Scrive, even engineers who were once QA’s are invited to try out Haskell (and Elm), and they sometimes even stick to it! Since the company uses mostly “Boring Haskell” (except for a few complex abstractions here and there), the onboarding process is not so difficult once the developer starts to understand Haskell’s basic principles and syntax.
Have you built any internal libraries or DSLs to help model domain logic (e.g., document flows, signing rules, legal states)?
Yes! I joined a team within Scrive that had built its own DSL following the recommendation of Sandy Maguire in his book Algebra Driven Design (which I had to read, of course, haha). The domain was very specific to documents, signatures, and the way we handle them in the company, but the resulting DSL and property tests written as a consequence were really nice and incredibly powerful!
How do you approach GHC upgrades? Do you usually try to keep up with the latest stable GHC version, or do you stay on the version that works for you for as long as you can? How painful are GHC upgrades for you? Do they require a lot of work to build your whole codebase?
We upgrade to new minor versions of GHC based on how well-supported they are by the ecosystem and known regressions, the latter being the main adoption blockers for us.
Do you follow GHC development with regard to new features? Are you open to introducing them into your code, or do you prefer being more conservative? Are there any features added over the last few years that you find particularly useful?
We keep an eye out for the latest improvements in features that allow us to debug our systems in production in an efficient manner, like thread labels, backtraces, and callstacks. In this regard, GHC 9.12 brings many good things. We were very happy to adopt OverloadedRecordDot, which decreased our usage of the Optics library a lot.
Functional Mindset vs Business Constraints
How do you balance functional purity with product velocity, especially in a legal-tech setting where correctness is critical but deadlines are real?
Our tooling and performance team exists to lay reliable foundations upon which we can build rapidly. Percentage-wise, the majority of “new” features are built upon existing features. We rarely have to rebuild something from the ground up. Moreover, our QA team ensures that what we deliver is up to spec. They maintain their own list of invariants to check for, and they are a big reason why we deliver quality software today.
Do you feel that using Haskell has shaped the way your team thinks about problems, not just technically, but organizationally or culturally?
I think we are using Haskell in a practical way and not an academic way. Outside the scope of a single service, I see no difference from other tech companies that could possibly be influenced by tech choice. Having said that, working in a company full of functional developers (frontend and backend) is quite a delight to be honest :)
The Road Ahead
Are there areas of Scrive’s platform where you’re planning to increase (or reduce) Haskell usage in the future?
While backend services for the main product suite keep being written in Haskell, we are also letting other teams (integrations, analytics) use the tools they are comfortable with.
If you had to rebuild a critical part of your system today, would you still choose Haskell, or would another tool be more appropriate now?
Considering our investments in development experience and the in-house expertise: Yes.
Thanks Flávio for this interview! Flávio website Flávio Twitter Scrive website Scrive LinkedIn