This blog just passed the 7 year mark from our initial "Hello World" post. We've always built and hosted our own blog, initially using OctoPress but eventually migrating to just plain old Jekyll.

Artsy uses 3 separate editorial platforms now, we built our own for Artsy Magazine, use Medium for our Life at Artsy blog and Jekyll for the engineering blog. There was a healthy debate about whether we would migrate to one, or two systems, but I had pretty strong opinions on migrating the engineering blog to Medium and nipped that in the bud pretty quickly.

With Signal vs Noise being a high profile of a example of migrating to Medium and back again, I thought it's worth taking the time to examine our reasoning for doing it ourselves.

Read on →

At the beginning of January we discovered an interesting note in TypeScript's roadmap about linting:

In a survey we ran in VS Code a few months back, the most frequent theme we heard from users was that the linting experience left much to be desired. Since part of our team is dedicated to editing experiences in JavaScript, our editor team set out to add support for both TSLint and ESLint. However, we noticed that there were a few architectural issues with the way TSLint rules operate that impacted performance. Fixing TSLint to operate more efficiently would require a different API which would break existing rules (unless an interop API was built like what wotan provides).

Meanwhile, ESLint already has the more-performant architecture we're looking for from a linter. Additionally, different communities of users often have lint rules (e.g. rules for React Hooks or Vue) that are built for ESLint, but not TSLint.

Given this, our editor team will be focusing on leveraging ESLint rather than duplicating work. For scenarios that ESLint currently doesn't cover (e.g. semantic linting or program-wide linting), we'll be working on sending contributions to bring ESLint's TypeScript support to parity with TSLint. As an initial testbed of how this works in practice, we'll be switching the TypeScript repository over to using ESLint, and sending any new rules upstream.

At Artsy we've been using TSLint for a few years now; it's worked well for us, and we've even written our own custom rules. However, given the vastness of the JS ecosystem and how fast it moves, it's easy to recognize this announcement as an exciting moment for tooling simplicity.

Read on →

Interviewing is hard. Interviewers want to make sure they're hiring the person who will add the most value to their team; candidates want to make sure they're joining a company that aligns with their goals and perspectives.

Recent trends in hiring are white-boarding sessions, trivia questions, and hours of take-home assignments. At Artsy, we don't use any of these. We often get asked why not - and how we assess technical skill without them.

Read on →

At Artsy we’ve been moving towards GraphQL for all of our new services. Acknowledging GraphQL is a relatively new technology, we faced some challenging questions as we were developing one our most recent services.

Naively as my first attempt to define GraphQL types and schemas, I naturally tried to map our database models to GraphQL types. While this may work for lot of cases, we may not be utilizing some of the useful features that come with GraphQL that can make the consuming our data a lot easier.

GraphQL: Interface or Union?

Think of the case where we are trying to expose search functionality and the result of our search can be either a Book , Movie or Album. One way to think about this is to have our search query return something like:

Read on →

Last year, I wrote about the process of fully automating our weekly engineering-wide standup. One of the benefits of automating what was a meeting run by a single person to a meeting run by everyone is that we removed a single point of failure. However, I may have fibbed just slightly when I called our standups fully automated.

This blog post is going to cover how (and more importantly, why) I finally automated the last 5% of our weekly standups. Let's go!

Read on →

It's been three years, and Swift Package Manager (SPM) is at a point where it can be useful for iOS projects. It'll take a bit of sacrifice and a little bit of community spirit to fix some holes probably but in my opinion, it's time for teams to start adopting SPM for their 3rd party dev tools.

TLDR: You should be using SPM for 3rd party dev tools like: SwiftLint, SwiftFormat, Danger, Sourcery, SwiftGen and Git Hook management.

This post covers: What made it feasible to use SPM now? What are the downsides of the status quo? Why use SPM at all? What are the downsides to using SPM?

Read on →

In the JavaScript world, the idea of deploying your libraries on every PR is pretty common. As someone who runs a dependency manager but comes from a native background, it's easy for me to cringe and imagine the strain this puts on NPM's servers. However, that is where the ecosystem is and continuous deployment can be really useful. So, about a year ago we started moving a lot of our libraries to do this at Artsy too. Starting with our most critical dependencies:

We started off using a commit message based workflow, but have just finished the migrating to a GitHub Label based workflow that is less workload on individual contributors. This post will cover how, and why.

Read on →

Last month I was chatting at a bar with an engineer working on the Swift team, and we welcomed someone to our conversation where they opened with the question: "When can I stop using CocoaPods and switch to Swift PM?" I chuckled, because I get this a lot (I have been helping to maintain CocoaPods for about 6 years now) but they had made mistake of asking an Apple employee about something which sounds even remotely like a future product question. So, it didn't go anywhere.

Well, person whose name I don't remember, let me try to re-frame that question into something I can take a reasonable stab at: "Why are we all still using CocoaPods now instead of Swift PM for iOS apps three years after its release?"

Read on →

Micro-Services make sense for an engineering team of our size. You can scope a domain of your business to particular small unit of abstraction like an API. Doing so makes it easy to work in isolation, experiment with new ideas and evolve in many directions.

We've been carefully pushing for years to move away from our single monolithic API, to a collection of smaller, more focused projects. Our highlights docs showcase this well. The movement to smaller composable services works great from an isolated platform/systems perspective but can be a bit tricky to handle with front-end clients. Until 2018, the way that we've addressed the growing complexity in our service later has been to migrate the complexity inside our main GraphQL API, metaphysics. Metaphysics is our GraphQL API gateway that consolidates many API sources into a single service, then extending and interleaving and their data to make clients easier to write.

However, as more services have been created, and grown - so has metaphysics. This creates a worrying trend, as the growth of code in metaphysics isn't quite linear.

Our main line-of-thought on how to address this is via GraphQL schema stitching. We've been running experiments in stitching for over a year, and have have been running with stitching enabled in production for a few months.

Read on →

Hi! Let's talk a little bit about user authentication. We'll discuss it through the context of authentication within Artsy's ecosystem of applications, but ideally the same concepts will translate into other systems as well. The goal here is to build an understanding of (1) what exactly authentication is, (2) how it works, and (3) how to use artsy's specific infrastructure to delegate authentication for a new application to the existing ecosystem.

There are two primary authentication flows that we use at Artsy. We support user authentication through OAuth to allow users to log into our applications by delegating authentication to Gravity, our primarily application API. Alternately, we support app authentication for those cases where an application will only be called by other applications. We don't care about user authentication in this context, there's no need to redirect to a login screen etc - we just need to establish permissions between services. In both cases you'll be working with JSON Web Tokens (JWTs), and the difference is how the token you're looking at is generated.

User authentication happens at login - when the user provides their credentials to our server, our server confirms that they are who they claim to be and then generates a cryptographically signed token that encodes a few facts about that user.

App authentication, by contrast, all gets done in advance. We create the token manually, and share it with whatever application we want to grant access to.

In this document we'll first develop an understanding of what OAuth is and how it works. Then we'll examine the tokens we're using to get a better sense of what kind of information we have to work with. Finally, we'll go into how to set up authentication for users and for applications, building on the knowledge we've established.

Read on →