Overnight transition to remote work for leaders

Has the latest once-in-every-50-years species-threatening pandemic confined your team to your respective homes? Do you still need to ship product, make customer calls and maintain a regular meeting cadence to avert chaos? Don’t we all.

Every team faces a set of common and entirely predictable issues in the switch to remote work, and I want to share a few core practices that worked well for us at Freckle. We started remote work around 2015 when, as a tiny K-12 education startup, we struggled with hiring locally the kind of talent we wanted on our team. Since then, 70-80% of the company has become remote, allowing us to build an exceptional team we would have never put together in the Bay Area alone. Remote-accepted became remote-preferred, and eventually remote-only, with the unfortunate occurrence of COVID-19.

Here are the basics.

Prepare the new home workspaces

Photo by JC Gellidon on Unsplash

If you spend 16 hours a day in front of your home computer screen like I do, you might find it hard to believe that not everybody already has a dream workstation setup at home. Mind blown, right? A desk, a quiet room, an ergonomic monitor setup, and a stable Zoom-friendly internet connection aren’t a given for many, but are essential for productive work sessions at home. The last thing you want is to fight your environment.

What can you do, then, to support your team members who aren’t properly set up yet?

If you still have access to your office, then I recommend reimbursing last-minute Lyft rides to pick up whatever supplies your employees might want to move to their homes. For anything less urgent, an overnight Amazon or Monoprice delivery will take care of basics such as monitors, cables, and office chairs. Consider going the extra mile and providing your suddenly-remote employees with a home setup budget.

Reimburse your employees for part, or the entirety, of their internet bill. Some will not have a connection that can consistently handle a Zoom video call. This is critical for your customer-facing team members. Encourage them to upgrade their internet speed if they’re maxing out their bandwidth.

Employees who share their living spaces with others will also benefit from a headset with a directional boom mic. At Freckle, we’re partial to the Jabra Evolve 40 UC model, which does a great job at isolating the speaker’s voice in a loud office or call center.

This all assumes that all of your employees have access to an assigned work laptop that they can take home with them from the office. When that’s not the case, you will want to consider renting or acquiring devices ASAP.

Standardize communication tools

Photo by The Creative Exchange on Unsplash

Wearing PJs unfortunately does not exonerate you from meetings, team syncs, status reports and ad-hoc group debates. Among many of the social work processes, you still need to run your all-hands and get your teams informed, inspired and motivated to do their best work.

Good news: when everyone is remote, meetings are actually easy. There’s no fiddling with conference webcams, awful large room acoustics — huh, what did the quiet guy in the back mumble? — and having to remember to regularly pause for your remote attendees to make sure they get a word in over people vigorously arguing in the room.

Bad news: you have to overcommunicate. Before, gaps in shared information might have been accidentally overcome through hallway whispers, overheard conversations and lunchtime catch ups. Now, getting the full story to your whole team must be a concerted effort. Many books have been written on company-wide communication alone, so I won’t attempt to squeeze that into a couple of paragraphs. A simple guideline is that you will not be able to overdo it; too much information is better than not enough. Also create a regular cadence for sharing info with your team, if you’re past the point where you can get away with one single Slack channel for all the latest company news.

What about tools, though?

Email is always there for anything that must not be missed, and requires more careful reading and permanence. Good old email is still your Swiss Army knife of information dissemination. For anything less ethereal, group chat tools like Slack are a time-tested solution — at least in startup dog-years. Tandem or Slack video calls can be great for impromptu chats, just be considerate about how and when you pull people out of their flow.

For video conferencing I’m biased toward Zoom, with its gallery view feature. It’s consistently fast, has miraculously not collapsed yet under the extra Coronavirus-induced traffic, and it’s free for K-12 schools impacted by the virus.
Tip #1: the Zoom calendar integration for O365 or G Cal is essential to making sure there’s always an associated Zoom link with every meeting. The last thing you want is for people to roam your Slack channels asking for a meeting link. It must, must be there in the calendar event itself.
Tip #2: the /zoom integration for Slack is also nothing to laugh at and adds a quick pathway to starting an impromptu video call.
Tip #3: this should go without saying, but it’s still pervasive: make sure your video is on during calls. Many teams will devolve to audio-only, but that removes a lot of important communication information that we (mostly) hairless primates rely on to interact with each other.

You should let teams pick their tools, but your company’s core communication infrastructure is something you want to standardize.

Brace for distractions

Photo by ROBIN WORRALL on Unsplash

Unless you’ve done this before, your first impact with the new work environment is going to be full of character-building lessons. Family members and pets will be confused about why you’re stepping on their routine. Your brain will associate home with fridge runs, naps and refreshing Twitter, not with staying focused on the task at hand. Motivation sags, the natural accountability of the office goes away. You wonder how anybody gets work done like this. And if you still have that last stick of string cheese left in the fridge.

Turning home-mode into work-mode is not easy, but it can be done. Set up your desk in a way that screams “work”: keep it clean of distractions and unrelated items. Just your laptop and your notes. Consider keeping your personal phone somewhere else to avoid the temptation. If you’re fancy, have a separate desk or room just for work. It’s tough for those of us who live in 500-square-foot studios in San Francisco, but your situation might be more conducive.

This is trite, but it works: dress as if you were going to work. Don’t go full suit unless you have to, but consider tech-casual or business-casual. It’s hard to negotiate budgets or fix a network outage in your datacenter with no pants on.

Set expectations with those around you that, despite being at home, you’re actually working and your job expects you to be available with minimal distractions. Again, looking like you’re working helps with this. Your cat won’t care, but there are exceptions to every piece of advice.

Hold space for feedback

Photo by You X Ventures on Unsplash

Let’s go meta. At Freckle, we get a lot of value from having a #remote channel on Slack for surfacing concerns, feedback and ideas on how to make our remote workflows better. It’s a great place to raise issues likely affecting several people and see if anyone has found a workaround.

For example, when we still had an office, our remote staff couldn’t hear one of the conference rooms that well. People didn’t want to bring the issue up, concerned it might be only a problem on their end and it was maybe their fault. Receiving confirmation from others in the feedback channel helped show enough traction to warrant upgrading the mics in that room to a different system.

Additionally, consider having a biweekly or monthly remote hangout, and put feedback exchange on the agenda. With the team no longer having a physical space to voice concerns, having an allocated time to exchange ideas is going to pay dividends over time.


Switching to remote work in a pinch can be confusing, but if you address these four broad categories, you’ll have the fundamentals handled, and will be able to iterate further from there.

  1. Set up your new work environment for optimal ergonomics and availability for video conferencing
  2. Standardize all communication tools across the company
  3. Expect distractions, and to deal with them one at a time.
  4. Share feedback about your experience with remote work with the rest of the team, and iterate on it together.

(Featured image: Photo by Anna Auza on Unsplash)

Overnight transition to remote work for leaders

Haskell at Front Row

I wrote this post originally for the Commercial Haskell SIG

The mission

Front Row Education was founded to change the way math education is done in a modern day classroom. In the web universe we have all sorts of great tools for tracking, analyzing and incentivising user behavior: complex analytics, rich data visualizations, a/b testing, studying usage patterns over time, cohort analysis, gamification etc. We figured: instead of using the above to have granny click on more ads, let’s make these powerful techniques available to teachers, parents and school administrators to make math education more engaging and effective.

Front Row allows schools to track student progress over time, identify areas of struggle, learn how to address them, all the while encouraging more quality practice. Learning math this way becomes a interactive and compelling experience, providing immediate feedback and adjusting content with every answer. As students practice, they generate rich data that school staff uses to continuously course-correct and fill in the gaps.

Numerous experiments from past years show that making Front Row a regular part of a math classroom leads to improved conceptual understanding, a lower rate of students falling behind, and improved scores on state tests. As of today Front Row helps over a million students in their regular math practice, and has been used in over 30% of US K-8 schools.

Our journey to Haskell

As of today Front Row uses Haskell for anything that needs to run on a server machine that is more complex than a 20 line ruby script. This includes most web services, cron-driven mailers, command-line support tools, applications for processing and validating content created by our teachers and more. We’ve been using Haskell actively in  production since 2014.

At the time of the switch we were already familiar with the functional programming world. The central piece to the Front Row system is the JSON API used by both the student and teacher web experiences. I wrote the first version of the API in 2013 in Clojure on top of the Ring/Compojure micro-framework. At the time I didn’t have plans for the API to grow to serve the kind of size and traffic we see today: it was mostly a way for me to really dive into functional programming and understand design challenges that other popular frameworks had to come across.

Building your own framework is a fantastic learning experience, but it is also a significant commitment: without investing a ton of time and effort into the framework, you’ll end up with something very bare-bones and hard to turn it into a production quality, fully-featured application. It takes innumerable iterations to make a framework extensible, modular and well maintained with a team of 1-3 developers, busy with dozens other tasks that a fast-moving startup demands.

Clojure at the time didn’t offer any alternatives as far as web frameworks were concerned, and we were already starting to see the inherent critical weakness behind building large modular systems in dynamically typed languages: refactoring is a serious pain and something you will avoid at all costs because it’s hard to ensure you’re not breaking anything. It’s not that bad if you have ONE codebase that doesn’t have dependencies, but once you get into two digits you’re in for a bad time.

Switching to Haskell and the Yesod framework seemed like a natural step forward: a strongly typed, purely functional, highly expressive language that would finally allow refactoring and moving fast to be painless. On top of it, a beautifully designed, extensible web framework with years of polish, one of the best high-performance web servers in the industry, extreme attention to type safety, and an all-star team of OSS contributors supporting it.

Moving from Clojure to Haskell didn’t feel like a massive jump: a lot of concepts translate pretty closely, although Haskell offers a much richer vocabulary than just maps and vecs. Monads, type classes, IO etc. eventually clicked, and it was smooth sailing after that.

Advantages of using Haskell

Where does Haskell fit into all of this you say? As the development team of a small early stage edtech startup, we have two main goals:

  1. Iterate as fast as possible on new educational concepts, business model experiments and user feedback. Basically, crank out as much code as possible while keeping the quality bar very high.
  2. Stretch our runway, be conservative with our very limited resources

Haskell fits in pretty well with both of goals.

Static typing

First of all, static typing is essential when it comes to keeping the system always in a working state. Coming from a dynamically typed universe, it’s surprising how much time you can save on writing unit tests, because you are getting more certainty from the compiler: no more null exceptions, no type mismatches in function calls, no more forgetting about dealing with the empty list case etc. A whole class of pesky, incredibly common and banal bugs is eliminated from your work: you now have more bandwidth to worry about implementing user stories instead of obsessing that your application doesn’t blow up due to sloppy oversight.

I still remember one of my biggest Haskell/Yesod “aha” moments: not only does Yesod make sure that routes in your HTML are type-safe, but even image files linked in < img > tags are verified to exist on disk by the compiler. No .jpg, no build, it’s that simple. It’s a level of guarantee that dramatically increases your confidence in the code at barely any cost.


Modularity is another big one. We have a central module at the bottom of every one of our web applications, APIs, tools and cron binaries. This module wraps the database entities and the SQL logic necessary to access them. It also provides a lot of common shared functionality that should not be implemented more than once. Since the schema changes very aggressively, we need a way to make sure our applications are updated ASAP, we can’t wait for things to blow up in production. Updating our entity definitions in that one module prevents every application built on top of it from compiling again until the change is dealt with.

No more API call mismatches, no more using an old schema, no more apps running against an old deprecated version that can lead to breaking the db state. As many others have stated, Haskell is the first language out there that feels like it manages to achieve true modularity: purity and defining what context a function is allowed to run in ensure that a library call can lead to no surprises. Testing side-effect free functions is much simpler than continuously dealing with system state.


Regarding the second point, why would Haskell stretch your runway? Simple. You’re writing fewer bugs, you’re reusing more code, new developers are causing less damage, and you have more room to deal with technical debt before it bites you. Purity and static types allow a team to aggressively refactor the codebase without having to worry that they might have forgotten to update something: a combination of a light layer of spec-style tests and a very picky compiler provide you with most of what you need to make refactoring a non-issue. More refactoring = more long-term productivity, higher team morale, more pride in one’s work. Doing the same with a Ruby is as fun as pulling teeth.

All of the above adds up to needing fewer developers, as less time is spent on maintenance, which ultimately equals a higher chance of your company getting somewhere thanks to the more frequent iterations. The more stuff you try, the more likely you are to find or expand that business mechanic that will carry your business forward.

Trouble in paradise

Things aren’t all perfect though. There are still quirks and plenty of room for improvement in the ecosystem.


Build times, especially once the whole constellation of Yesod and Persistent packages are brought into the mix, are not insignificant. It still takes a good 5-10 min to build our larger web application on our beefiest machines. There are optimizations that can be made in this space which we haven’t adopted yet, such as caching already build object files to avoid having to re-compile them every time, so I’m confident this will be a non-issue in the nearby future, but it’s still worth being aware of. GHC works hard, you need to provide it with enough juice or time to let it do its job.


The testing frameworks out there are still fairly spartan from the developer experience standpoint. If you test Yesod with hspec, the premier BDD library for Haskell, there’s currently no way to insert a bunch of rows into the database during fixtures and pass the results into the individual test cases. You have to wrap each test case in additional
function calls to pull that off, adding more boilerplate to your tests.

Additionally, it’s not possible to find out which one of your specific test cases failed when checking for multiple conditions within the same “it” block. This means that if you need to check the state of the system after an HTTP request, you have no clue which one of the checks failed.

Fortunately the developer(s) behind these libraries are responsive and happy to look into improvements. At the very least they’re glad to point other developers in the right direction towards a PR.

This has in general been my experience with the Haskell community: things aren’t perfect, but folks are always looking for a way to improve the ecosystem and want Haskell to be the best language to develop in. People are trying to carve out their little slice of paradise, and are willing to put in the hard work to make it happen.


Documentation is still not quite there and the initial onboarding of new developers is still rough. There are only so many snippets to Google for, compared to e.g. Ruby and Python. A lot of documentation is very barebones and requires diving straight into the source, which is fine for a proficient Haskeller, but not for an already terrified beginner.

Many times I’ve witnessed senior developers get very frustrated when something wouldn’t compile for hours and they couldn’t find any help to move forward: be prepared to assist them before they get too grumpy. Some projects are better about it than other: Yesod and Persistent have extensive documentation and the FPComplete crew have numerous tutorials out there to help. New books come out once in a while with fresher snippets: the time-tested Real World Haskell is now fairly outdated, but the more recent Beginning Haskell is perfectly relevant. Many channels on IRC are available:
#haskell-beginners, #haskell and #yesod, although sometimes it can take work to get the answer you’re looking for. More than once I heard the comment that documentation seems to be written by wizards for other wizards, and if you’re a lowly initiate, you will have a rough time.

I’ve personally had the privilege to help all of our developers skill up in Haskell and Yesod, and I’ve become a huge believer in the power of having someone more experienced guide you along the way. What took me several months of learning, mostly by myself, now takes our developers a couple of weeks of quality coaching. It took me a while to grok monads, type classes, type families etc., however, properly guided developers can figure it out in a matter of hours. Having a good teacher on your team will speed adoption within the organization immensely.

Strength in numbers

We once experienced a very frustrating issue that got us thinking about our full commitment to Haskell as a company.

When we switched our main API to Yesod (a full rewrite), we almost immediately ran into the issue the API would burn up close to 95% of available CPU on whatever AWS EC2 instance it was hosted on. We upgraded machines, just to see if we could cheat our way out of fixing this by throwing money at the problem, and even with a $600/mo 16 core box, the API still managed to flood all of the available cores with barely any traffic hitting it. I personally spent a good week banging my head against it: was it resource contention? Was it a really big oversight in one of my handlers? Was it misconfiguration? Was it something about the EC2 environment? Why doesn’t this reproducing AT ALL under profiling? Was it our database connection pooling? I threw a lot of screenshots and code samples at the community both on Google Groups and IRC: nobody else had ever seen anything like it. Uh oh.. All the while customer support requests are pouring in,
teachers are aggravated, the team is looking at the devs and “their latest shiny toy”,  tapping their collective foot.

This is the part where picking exotic tooling for your stack can be a dangerous beast: “given enough eyeballs, all bugs are shallow”, and when only a dozen teams out there are using your libraries at your scale, you are on your own when it comes to fixing issues. With Rails, there’s enough volume of developers that there will be enough projects of every scale to burn-in your tool of choice. That’s simply not the case with Haskell’s usage numbers.

What this means is that if you’re planning to bet the farm on Haskell, you need to be ready and comfortable with the idea that you might have to get your hands dirty, might be the first person to figure out a solution to the problem you’re seeing. This requirement is pretty much non-existent in .NET / ruby / python at al. Start small, start simple, let the tooling grow on you as you gain experience. Start with tools that aren’t mission critical until you’re more confident.


It bears mentioning that the above concerns are being actively addressed by the community and the state of things is rapidly improving:

  • Cabal, the Haskell package manager, was a real pain to work with just a few years ago and “cabal hell” is still part of Haskell vernacular. However, with sandboxes and consistent version snapshots provided by FPComplete as Stackage LTS, that problem has been mostly resolved.
  • Build times are slow, but the community is coming up with improvements such as halcyon that should alleviate things considerably.
  • Docs have gotten dramatically better over the past couple of years. There’s been a big push towards keeping fresh, community-maintained, easy-to-follow and beginner-friendly instructions such as those provided by Chris Allen’s Learn
    . We now even have IRC channels tailored specifically for beginners, e.g. #haskell-beginners . Today newcomers become more productive much faster than they did a few years ago.
  • The community has been recently doing a better job at outreach and we’ve seen many new developers come make Haskell a permanent part of their toolbox. With more participants, tools get more fully-featured and more maintained.


It’s a very exciting time in the history of computing to jump on the Haskell train. Yes, the community is tiny and one might get little hand-holding compared to more popular ecosystems, however Haskell offers obvious benefits to software teams who can power through the initial pain period.

Today Haskell offers some of the best tools around for delivering quality software quickly and reliably, minimizing maintenance cost while maximizing developer enjoyment. To me Haskell is that dream of “developer happiness” that we were promised many years ago by the Ruby community: I can write beautiful, short, expressive and readable code that will perform phenomenally and stand the test of time and continuous change. What more can I ask for?

To find out more about Front Row, visit us at https://www.frontrowed.com. You can also follow me at https://twitter.com/alex_kurilin

Shameless plug: we’re hiring. Currently looking for a Founding Systems Engineer with DevOps focus.

Haskell at Front Row

Upgrading Yesod 1.2 -> 1.4

I’ve recently had to quickly upgrade Yesod 1.2 web application from version 1.2 to 1.4. I was looking for resources on how to do this and couldn’t find anything beyond Announcing Yesod 1.4 and Persistent 2.1 Released. This post should be useful if you’re in a similar situation and your app is backed by PostgreSQL, even though it should work just about the same for any other SQL backend.The transition was actually pretty simple, you have to take care of the following steps:

Update the libraries

Installing Yesod 1.4 through hackage is even more of a pain that before. It’s doable, and I have done that before, but I strongly recommend using Stackage Server. Go with an exclusive snapshot to avoid headaches and having to set constraints. It completely takes care of cabal hell as long as your dependencies aren’t highly exotic. Even then there are ways to work around it, but that’s for another post.

Once yoru cabal is wired against Stackage, remove version constraints from all of the packages in your .cabal file, as those will be decided for you by the Stackage snapshot.

Update Foundation.hs

-- replace this
import Database.Persist.Sql (SqlPersistT)
-- with this
import Database.Persist.Sql (SqlBackend)


-- replace this
giveUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
-- with this
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")

Add the following after all of the implementations of instance YesodAuth:

instance YesodAuthPersist App


-- replace this
share [mkPersist sqlOnlySettings, mkMigrate "migrateAll"]
-- with this
share [mkPersist sqlSettings, mkMigrate "migrateAll"]

Update SQL entities

Love timestamptz in Postgres? ZonedTime SQL type is gone in Persistent 2.1: it’s now officially replaced with UTCTime which was already available before. If you actually need to know the TZ of a certain timestamp, you’re going to need a custom solution, Persistent isn’t going to do this out of the box, but if you don’t, just swap one for the other.

Update Entity Key creation logic

If like me you were manually generating Entity keys in your tests, then you will no longer be able to do so with Persistent 2.1. Replace your old code doing:

Entity (Key $ PersistInt64 1) { foo = "bar" }

with the new:

import Database.Persist.Sql
Entity (toSqlKey 1) { foo = "bar" }

The steps above should take of the most common conflicts that you will encounter when upgrading PostgreSQL-backed Yesod 1.2 to 1.4. Let me know if it’s missing anything.

As always don’t forget to drop by #yesod and #haskell-beginners on Freenode if you have any questions.

Upgrading Yesod 1.2 -> 1.4

Reference Haskell libs for developing great style

Been somewhat busy digging into Haskell recently for our analytics-heavy upcoming web app and couldn’t get a good idea of what quality Haskell code should look like. Sure, there’s LYAH and RWH, and Beginning Haskell, but I like to see live code form authors who are universally considered reputable and well understandable by beginners such as myself. The following libs were recommended for perusal by the fine and generous folks at #haskell-beginners:

There are also a couple of good Stack Overflow posts on the subject if you need more examples:



This should be plenty of reading, back to work.

Reference Haskell libs for developing great style

Early/mid 2014 update – we’re hiring

Whoa, a few months have gone by really fast here. Hi world. Guess I should post an update.

Been hard at work as usual at Front Row, it’s been very interesting to watch our numbers go up at a staggering pace while the # of people supporting the project stays the same. Really makes you appreciate the people making it happen, the tools you’re using and the best practices that keep the whole system from falling apart.

In any case, a few folks and we decided that it was time to give Front Row a bit of a budget to start scaling things out. We’re now looking for a couple of engineers to join us and work closely with yours truly. We’re seeking  web generalists with strong interest in functional programming: we’re a very small team and being able to pick any part of the stack up in a few days is very important. Here’s more info.

Whatever you like, we got it:

  • Want to build super-interactive SPAs and get good at data-visualization? Check.
  • Want to get your hands dirty with ops, configuration management, build automation and continuous delivery? Love Ansible? Check.
  • Want to crunch a ton of data and serve it to the outside world with Clojure and Haskell? Check.
  • Want to build tools and pipelines that enable Front Row content creators to publish their work to hundreds of thousands of students? Check again.
  • Love DBs? We do too! Ours is growing exponentially 😦 If you’d like to contain the beast, we can keep you busy.

That’s it for now!

Early/mid 2014 update – we’re hiring