Frictionless Development

Too often I find myself fumbling through the same set of issues around deployment and frontend development that distract me from focusing on business problems.

What's easy in deployment: spinning up machines, configuring firewall rules, managing access/keys, OS package security updates. What's hard: managing nginx config (subdomains, CORS, websockets, cache), frontend and backend play well, updating HTTPS certs, ensuring deploys don't cause downtime.

What's easy in frontend dev: JWT-based user session management, Web Components based development. What's hard: updating individual libs for critical bugs or security issues while ensuring different lib versions still play well.

By 'hard' I don't mean hard to solve, but tedious because it's a similar set of problems and decisions for every new microservice or project.

Microservices have been a huge blessing in the sense that they've allowed us to focus on the current project at fast pace with zero side-effects on product aspects that are already in production. Older projects only receive security-related version bumps or rare bug-fixes.

We're starting to settle on some conventions — code is deployed as "services", each service has its own (sub)domain, a service could have a frontend web UI component served at / and a backend server component served at /api, served over HTTPS. Backends are written in either node.js (TypeScript) or Python and typically expose a JWT-auth'd GraphQL endpoint. Deployment is using Ansible, and we ship code using docker and docker-compose.

Frontend is AngularJS or Angular 8 moving forward. The React ecosystem continues to feel duct-tapey despite being backed by tons of organizations. Over time, I've found myself mixing and matching different libraries for state management and form handling, and although each attempt initially felt productive, the end result was a bit of an eye-sore.

Angular had its own issues in the past. Development in React was clearly faster, better. But with Angular 8, I think the Angular team gets a lot of things right, inspiring confidence that the community driven effort to develop major pieces together will receive support for years to come. There's a sense that devs can adapt to the latest and greatest in ES, browser features and TypeScript at their own pace without worrying too much about having a broken project.

From a consulting standpoint, I've invested time in React, Redux, more recently MobX, and I don't see tremendous pragmatic benefit from the final UX standpoint — the AngularJS SPA I wrote 2 years ago works just as good, though a major gripe is that it's painfully slow to load initially. I find the AngularJS codebase easier to maintain, and the React code at a component level feels spaghetti-ish. CSS-in-JS makes my skin crawl so I worked around that, but it still "feels" like a lot of boilerplate (actions, reducers)...sometimes to do something very simple.

Angular 8 offers skills transferable across projects and a (supposedly) easy-to-upgrade ecosystem. What sold it for me: Angular's strong opinions around Forms (validation, error handling) and the more recent code-splitting and SSR features make it a stack worth devoting energy for better ROI. 80+% of my pain is dealing with user input, 10% is some sort of complex rendering requirement (mainly datatables), and the rest possibly deals with routing, user nav, state management in the SPA. Choosing Angular also bodes well with our backend choice — NestJS — which shares much of its component-based code organization and IoC ideas with the Angular project.

I think these fairly simple, stable choices enables us to move faster. Technology improves crazy fast, and we continue to pick up and evaluate hip new things that could help us move faster. You don't always find a perfect fit - for e.g., I spent a week looking into Kubernetes only to conclude that we didn't need it. But it's important to have an open mind and keep up with what's going on.