<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Yenkel's Blog</title>
        <link>https://yenkel.dev</link>
        <description>A blog about software development and other things</description>
        <lastBuildDate>Sat, 07 Mar 2026 12:17:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved 2026</copyright>
        <item>
            <title><![CDATA[MDX and Vercel with gatsby starting lumen]]></title>
            <link>https://yenkel.dev/blog/mdx-and-vercel-with-gatsby-starting-lumen</link>
            <guid>https://yenkel.dev/blog/mdx-and-vercel-with-gatsby-starting-lumen</guid>
            <pubDate>Sun, 14 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[To create my new blog I took the to gatsby-starting-lumen starter and modified it to add MDX support and deploy it with Vercel]]></description>
            <content:encoded><![CDATA[
# The new blog
I had been meaning to start a new blog for a while. After some thinking I decided to use [gatsbyjs](https://www.gatsbyjs.org/), that I'd want [mdx.js](https://mdxjs.com/getting-started) support and to host in on [Vercel](https://vercel.com/):
- I decided on mdx was mostly because "it is new(ish) and I want to try it out"
- The Vercel decision was mostly because I think it is a great service and I know a number of people that work there 😁

I looked at various Gastby templates until I caught one that caught my eye: [gatsby-starter-lumen](https://www.gatsbyjs.org/starters/alxshelepenok/gatsby-starter-lumen/). I liked the base theme, its support for Google Analytics, Disqus comments, and mobile support. As someone that reads a lot on my phone I really, but also not a good UI developer, I really wanted my blog to be readable on mobile devices. Unfortunately, the template [did not support mdx](https://github.com/alxshelepenok/gatsby-starter-lumen/issues/302), it was built to deploy with Netlify. Thus, I decided to do adapt the starter to fit my needs.

# Adding mdx support
I found this [blog post](https://www.gatsbyjs.org/blog/2019-11-21-how-to-convert-an-existing-gatsby-blog-to-use-mdx/) on how to adapt the ["Gatsby Starter Blog"](https://github.com/gatsbyjs/gatsby-starter-blog) to use MDX. After following the steps described there (which mostly involved search + replace) it took me a while to realize I needed to make some changes to the `jest-config.js` file:

1. The `__PATH_PREFIX__` variable [was replaced](https://github.com/gatsbyjs/gatsby/pull/12128/files#r279947544) by `__BASE_PATH__`:
```js
globals: {
-    __PATH_PREFIX__: ''
+    __BASE_PATH__: ''
},
```

2. I needed to transform .md and .mdx files:
```js
   transform: {
-    '^.+\\.js?$': '<rootDir>/jest/jest-preprocess.js'
+    '^.+\\.js?$': '<rootDir>/jest/jest-preprocess.js',
+    '^.+\\.(md|mdx)$': 'jest-transformer-mdx'
```

3. And I needed to ignore `gatsby-plugin-mdx` in the jest configuration:
```js
   transformIgnorePatterns: [
-    'node_modules/(?!(gatsby)/)'
+    'node_modules/(?!(gatsby|gatsby-plugin-mdx)/)'
```

Only after having done all of that I actually found [this blog post](https://chrisotto.dev/gatsby-change-from-md-to-mdx/) that dealt with many of these details 😅. 

## MDX demo
The great thing is that now I can add JSX in Markdownn 🚀. If I add this code:
```js
<div><button>test</button></div>
```

A button renders:

<div><button>test</button></div>

Cool, right?



# Removing netlify
1. Delete the `netlify.toml` file.
2. Remove the entire `src/cms` directory.
2. Run
```
npm uninstall -S gatsby-plugin-netlify gatsby-plugin-netlify-cms netlify-cms-app
npm install -D @now/node
```
4. Remove the Netlify plug-in from `gatsby-config.js`:
```
-    'gatsby-plugin-netlify',
-    {
-      resolve: 'gatsby-plugin-netlify-cms',
-      options: {
-        modulePath: `${__dirname}/src/cms/index.js`,
-      }
-    },
```

# Adding Vercel support
Setting up Vercel is trivial (which is why I ❤️ it so much). Run `now` and confirm that you want to deploy the current directory:
```
➜  blog git:(master) ✗ now
Now CLI 19.1.0
? Set up and deploy “~/Documents/github/blog”? [Y/n] y
```

Pick your scope (in my case I was already logged in):
```
➜  blog git:(master) ✗ now
Now CLI 19.1.0
? Set up and deploy “~/Documents/github/blog”? [Y/n] y
? Which scope do you want to deploy to? 
● Damian Schenkelman 
```

Because the current directory is named "blog" I was asked if I want to link my current repository with that project. The .vercel folder was also created and added to my `.gitignore` file automatically:
```
? Found project “damianschenkelman/blog”. Link to it? [Y/n] y
🔗  Linked to damianschenkelman/blog (created .vercel)
```

After a minute or so the deploy finished. That's it 😱:
```
➜  blog git:(master) ✗ now
Now CLI 19.1.0
? Set up and deploy “~/Documents/github/blog”? [Y/n] y
? Which scope do you want to deploy to? Damian Schenkelman
? Found project “damianschenkelman/blog”. Link to it? [Y/n] y
🔗  Linked to damianschenkelman/blog (created .vercel)
🔍  Inspect: https://vercel.com/damianschenkelman/blog/35v6x3zvc [8s]
✅  Preview: https://blog.damianschenkelman.vercel.app [copied to clipboard] [1m]
📝  To deploy to production (blog-alpha-rose.vercel.app), run `vercel --prod`
```

## Vercel + Github integration
I also set up the [Vercel for Github](https://vercel.com/github) integration so pushing to GitHub automatically updates the blog. To do that I only signed in to my [Vercel dashboard](https://vercel.com/dashboard) and clicked **Import project**.
![](/media/2020-06-14/import_project.png)

Then click **Continue** to import a Git repository:
![](/media/2020-06-14/continue.png)

Type in the URL of the Git repository and click **Continue**.
![](/media/2020-06-14/import_git_repo.png)

That's it!

# Appendix: Fixing the jest snapshot tests
The original [gatsby-starter-lumen](https://www.gatsbyjs.org/starters/alxshelepenok/gatsby-starter-lumen/) has some Jest snapshot tests. For example, the Content.test.js file has this contents at the [time of writing](https://github.com/alxshelepenok/gatsby-starter-lumen/blob/951ab58d42aa25ab6dcf10ad40df6c74d038dcf0/src/components/Post/Content/Content.test.js):

```js
// @flow strict
import React from 'react';
import renderer from 'react-test-renderer';
import Content from './Content';

describe('Content', () => {
  it('renders correctly', () => {
    const props = {
      title: 'test',
      body: '<p>test</p>'
    };

    const tree = renderer.create(<Content {...props} />).toJSON();
    expect(tree).toMatchSnapshot();
  });
});
```

Fixing the tests is not required to get the blog to work, but I don't like changing code and breaking tests :). To support mdx, the `body` needs to be "wrapped":
```js
// @flow strict
import React from 'react';
import renderer from 'react-test-renderer';
import Content from './Content';
import prepareMdx from '../../../utils/prepareMdx';

describe('Content', () => {
  it('renders correctly', async () => {
    const body = await prepareMdx('<p>test</p>');

    const props = {
      title: 'test',
      body
    };

    const tree = renderer.create(<Content {...props} />).toJSON();
    expect(tree).toMatchSnapshot();
  });
});
```

And this is what `prepareMdx.js` looks like:
```js
// @flow strict
import mdx from '@mdx-js/mdx';
import { transform } from '@babel/core';

const transpile = async (content) => {
  const jsx = await mdx(content);
  return jsx;
};

export default async function prepareMdx(body: string) {
  return transform(await transpile(body), {
    configFile: false,
    plugins: [
      '@babel/plugin-transform-react-jsx',
      '@babel/plugin-syntax-object-rest-spread',
    ],
    presets: [
      require('@babel/preset-react'),
      [
        require('@babel/preset-env'),
        {
          useBuiltIns: 'entry',
          corejs: 2,
          modules: false,
        },
      ],
    ],
  }).code.replace('export default function', 'return function');
}
```]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[API Design Guidelines and API Linting]]></title>
            <link>https://yenkel.dev/blog/api-endpoint-design-guidelines-and-fitness-functions</link>
            <guid>https://yenkel.dev/blog/api-endpoint-design-guidelines-and-fitness-functions</guid>
            <pubDate>Tue, 16 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[How we are starting to scale consistency for HTTP API Endpoint design through guidelines and automating the guidelines through fitness functions]]></description>
        </item>
        <item>
            <title><![CDATA[A tale of latency and broken windows]]></title>
            <link>https://yenkel.dev/blog/a-tale-of-latency-and-broken-windows</link>
            <guid>https://yenkel.dev/blog/a-tale-of-latency-and-broken-windows</guid>
            <pubDate>Sat, 27 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Latency can get out of control because of small day to day changes. Dedicate a small amount of time to think about latency when making changes to keep it under control. parallel I/O, pre-fetching, and avoiding I/O are some simple techniques you can use.]]></description>
            <content:encoded><![CDATA[
# Latency and its importance
As a software developer you might be familiar with [the following table](http://norvig.com/21-days.html#answers)<a name="latency-table"></a>:
![](/media/2020-06-27/latency.png)


Even if the times are not exact and up to date for 2020, the gist of it is clear. Some operations (disk, network) are more expensive than others. When looking to minimize latency, start from operations that are more likely to take longer, because they are naturally slower due to hardware and speed of light limitations.

The importance of latency will depend on the software you are writing. For some software latency can business critical:
- [Real-time computing](https://en.wikipedia.org/wiki/Real-time_computing) where operations must guarantee completion under a deadline.
- A SaaS with latency SLAs that you need to meet for your enterprise customers 
- e-commerce that loses money when the site is slow (see this great blog post about [Amazon](http://blog.tacertain.com/p-four-nines/)).

You might also be writing software that you want to be "fast enough" or "not unnecessarily slow".

# Latency and broken windows
While getting to concrete latency guarantees for critical cases requires a lot of work and investment, it is also true that latency is one of those things that is easy to overlook unless you are paying attention. Over time, small decisions can pile up and you can end up with a product that is a lot slower than it should be mostly because of [accidental complexity, not essential complexity](http://faculty.salisbury.edu/~xswang/Research/Papers/SERelated/no-silver-bullet.pdf). 

The "broken windows" theory presents the problem in a nice way (From [wikipedia](https://en.wikipedia.org/wiki/Broken_windows_theory)): _The broken windows theory is a criminological theory that states that visible signs of crime, anti-social behavior, and civil disorder create an urban environment that encourages further crime and disorder, including serious crimes. The theory suggests that policing methods that target minor crimes such as vandalism, loitering, public drinking, jaywalking and fare evasion help to create an atmosphere of order and lawfulness, thereby preventing more serious crimes._
![](/media/2020-06-27/broken-windows.jpg)

Whether the theory is correct or not (there is an interesting chapter on this in the book [Freakonomics](https://www.amazon.com/Freakonomics-Economist-Explores-Hidden-Everything/dp/0060731338)) it is a useful context to talk about software. In the software industry, the Pragmatic Programmer book states ["don't live with broken windows"](https://www.artima.com/intv/fixit.html).
If we apply this to latency it is easy to reason that if you let small decisions/changes increase latency, over time the latency of the system will continuously increase over time. At some point, going back and figuring things out will be overly complex and sometimes teams decide to go for complicated solutions to solve this problem. We want to avoid that.

# Some real-life examples
One of the things we do at [Auth0](http://auth0.com/) is iterative delivery. Initial versions of code work and are tested, etc., but until we validate features with customers we avoid investing in optimizations. 

However, some things can be done in an initial implementation so we don't need to optimize later, as that's when as a developer you have the context about what you are doing. Re-thinking many small decisions a few weeks down the road is less than ideal. In this context, thinking about "expensive operations" latency wise is useful.

As part of a project, we are working on developing a new service (`new-service`) and adding some calls to it from an existing service (`client`). As we reviewed the changes we made to the `client` with the team, we found several opportunities for improvement.

The code snippets below are examples written using Javascript, but these ideas are language agnostic.

## Parallel I/O
> When I/O ops do not depend on each other and you need all data if possible use parallel queries.

Let's say a change to client code looked like this:
```js
     const a = await callExistingService(...);
+    const b = await callNewService(...);
+    // do something with a and b
```

The `getDataFromNewService(...)` call performs network I/O. Because we are working on this `new-service`, we know it also does more network I/O to talk to a database (which might need to do some disk I/O). All of these operations are naturally in the slow end of the spectrum from the [table at the beginning of this blog post](#latency-table).

If we can't avoid the operations, performing these in parallel yields some clear benefits. If the resulting code looks like this:
```js
const [a, b] = await Promise.all([
    callExistingService(...), 
    callNewService(...)
]);
```

If we call the time for these operations `t1` (`existing-service`) and `t2` (`new-service`), in the last example we change the latency from `sum(t1, t2)` to `max(t1, t2)`. That even means that if we don't want to make latency higher than the original, all we need to do is ensure `t2 <= t1`!

## Pre-fetching
> When I/O operations op2 only runs if op1 is likely to be successful, if op1 is likely to be successful in most cases, consider doing op2 in parallel ([pre-fetching](https://en.wikipedia.org/wiki/Prefetching)).

This case is similar to the previous one, but might be easier to miss. Let's say the code after the change looks like this:
```js
    const param = ...
    const exists = await callExistingService(param);
    if (!exists) {
        // handle edge case
    }
+   const b = await callNewService(param);
+   // do something with b
```

Both function calls depend on `param`, which is available before calling `callExistingService(param)`. If the likelihood of `exists` being false is low, then calling `callNewService(param)` in parallel is likely worth it. You won't be adding a lot more load to `new-service` in case `exists === false`, but you will be getting the aforementioned benefits for parallel I/O.

The latency improved code would look like this:
```js
const param = ...
const [exists, b] = await Promise.all([
  callExistingService(param), 
  callNewService(param)]);

if (!exists) {
    // handle edge case
}
// do something with b
```

## No-op
> When you can replace an I/O operation for a no-op, do it.

The best performance/latency optimization is a "no-op", i.e. figuring out how to prevent the call from happening. A simple way of doing this is caching. However, it is important to consider that caching does not need to be overly complicated and require every developer's favorite hammer [Redis](https://redis.io/). It just means _to store the value of computation to prevent performing the computation again_. 

The code we reviewed was doing this:
```js
    // somewhere
    const context = await hydrateContext();
    ...
    // later
+   const result = callNewService(context.param);
```

In this situation, the `client` had a way to store the result of a previous call to `new-service` that returned the same value. If `result` is relatively small and does not change it can be stored with the context and loaded as part of `hydrateContext()`. That way, the call we can simply avoid `callNewService(context.param);`.

The fastest call is the call that never happens 😆

# Conclusion
When you are working on code, don't [optimize prematurely](https://wiki.c2.com/?PrematureOptimization). I recommend, however, you add a "mental checklist" item to focus on latency and cross it off before submitting a PR. That will help you find [Donald Knuth's 3%](https://wiki.c2.com/?PrematureOptimization).

It is likely that just doing that and focusing on that latency for 10 minutes might point to small but valuable improvements that you can make, and accumulating latency over time.

Don't live with latency broken windows!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA['Jiro dreams of sushi' lessons for SaaS]]></title>
            <link>https://yenkel.dev/blog/jiro-dreams-of-sushi-lessons-for-saas</link>
            <guid>https://yenkel.dev/blog/jiro-dreams-of-sushi-lessons-for-saas</guid>
            <pubDate>Tue, 07 Jul 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[The documentary 'Jiro dreams of sushi' has some very interesting lessons for SaaS companies.]]></description>
            <content:encoded><![CDATA[
A few weeks ago I watched the documentary [Jiro dreams of Sushi](https://en.wikipedia.org/wiki/Jiro_Dreams_of_Sushi). I found it very interesting. The story of [Jiro's](https://en.wikipedia.org/wiki/Jiro_Ono_(chef)) pursuit of perfection, his sons, how passionate he is about his craft and his product is amazing. I strongly recommend it.

During the documentary I found myself noticing some interesting parallels between Jiro's business and [Software as a Service](https://en.wikipedia.org/wiki/Software_as_a_service) (SaaS), and I thought Jiro had some very good lessons for the SaaS world.

![](/media/2020-07-07/jiro.jpg)

# SaaS: Sushi as a Service 🍣
Much like Software as a Service (SaaS) [Jiro's restaurant](https://www.sushi-jiro.jp/dining-at-jiro/) has a clear product core that he and his team have spent years perfecting. Years ago Jiro decided his restaurant would only serve Nigiri(s), no other food (some visitors find this odd). This ensures he and his team can focus on perfecting their product offering over time.

However, even when he has this simple menu Jiro adapts his customer service to specific customer needs, using insights he has gathered from his customers over the years. 

A meal at Jiro consists of ~20 pieces of Sushi. Jiro serves the first piece to all customers at the same spot on their plate, and Jiro watches what hand each customer uses to pick up their food. If they pick up the sushi with their left hand, Jiro makes a mental note and from that point on starts serving left-handed diners at a different position in their plate, making it easier for them to pick the pieces up.

Another thing Jiro to prevent diners from getting full before trying all pieces is serve different size pieces to men and women, serving smaller pieces to women (whether that's correct or not is not the point 🤷‍♂️, it seems to work for him after years of being in the business).

Jiro and his team also make a point of having a repeatable and efficient way of  putting sushi in diners plates twice a day. One could say Jiro's team deploys multiple times a day (lunch and dinner) 😋:
![](/media/2020-07-07jiro-schedule.png)

They have established relationships with specific market merchants to purchase a particular fish type from each. Each vendor is a specialist in their fish type. Jiro trusts merchants to know their craft, and merchants, in turn, feel pride in providing Jiro. The process to prepare ingredients and even the process to hand make each piece of Sushi is repeated day in and day out the same way, which allows predictability and continuous improvement of their technique.

Finally, Jiro's place has [very comprehensive and simple to understand documentation](https://www.sushi-jiro.jp/dining-at-jiro/) on how to use the product.

# Lessons for SaaS companies 📝
These are the lessons I gathered from Jiro's documentary that I believe to be greatly applicable to SaaS companies, especially startups.

## Focus 
Do one thing well and perfect that. You might be tempted to _"add more dishes to your menu"_ aiming to please some extra customers, especially in the beginning. Resist that temptation if you have the runway, and you'll likely be more successful in the long run.

Multiple reasons can cause a company to "lose focus". One that's is fairly common is that while you and the team are building your SaaS product, you might run into situations when big customers want to pay you a lot of $$ for your product, only if you agree to build a certain set of features. What to do in this case depends on many factors, there are no easy criteria to say "yes" or "no". But over time these decisions accumulate, so you need to be intentional about them!

The more "one-offs" (features that are only valuable for one or a few customers) you do:
1. The more complex your product and codebase become, making development slower
2. The longer it takes to get to your original vision because you are spending time doing other things and because of the impact of #1
3. As a consequence of #1 and #2, the less motivated a team that believes in the vision will get.

As much as possible, once you have found product/market fit, try to resist the short term $$ temptation.

## Buy > build
Initially at a startup you are trying to minimize cash burn. This means you might build some rudimentary things instead of buying. 

If you get to a point when your company sees some success, changing mindsets and differentiating what your core is and what it is not is fundamental to grow and scale.

Jiro makes sushi. He does not fish his prawns. Unless it is your core business you too should prefer "buy over build". This helps increase [focus](#focus). 
Creating your container orchestrator, running your observability stack, or implementing your login 😛 are things to avoid as they reduce focus and increase cost in the long run.

For example: investing in observability (metrics, logs, tracing) is something all SaaS companies have to do, regardless of their industry. Unless you are extremely large and have particular needs (e.g. [Uber and Jaeger](https://eng.uber.com/distributed-tracing/), [Facebook and Scuba](https://www.facebook.com/notes/facebook-engineering/under-the-hood-data-diving-with-scuba/10150599692628920/) or [Google and Borgmon](https://landing.google.com/sre/sre-book/chapters/practical-alerting/)) you shouldn't be implementing an observability stack (and ideally not running it either).

Many OSS projects and SaaS companies exist so you don't have to, and projects like [Prometheus](https://prometheus.io/) and companies like [Honeycomb](https://www.honeycomb.io/) are respectively inspired by Borgmon and Scuba.

Pick your vendors and/or projects and use them. Don't spend time implementing observability tools from scratch unless that's your core business value.

Today at Auth0 we use [Datadog](https://www.datadoghq.com/) for metrics, [Elastic and Kibana](https://www.elastic.co/) for logs, [Lightstep](https://lightstep.com/) for distributed tracing and [Sentry](https://sentry.io/welcome/) for error tracking.

## Always learn from customers 
Even when you have a SaaS product, all customers are unique. Learn from them, listen to them and over time you'll be able to figure out what things you can do to provide a better service to all your customers. Take every opportunity to improve!

At Auth0 we constantly strive to learn from customers and prospects: early access programs, monthly or quarterly customer reviews, specific feature discovery sessions, and support tickets are some ways customers provide feedback. Whenever we build something we always think about how customers will use it.

Even today, after 7+ years and 🦄 status, my friend [Matias Woloski](https://twitter.com/woloski)(Auth0 CTO & co-founder) continues to reach out to [individual customers on Twitter](https://twitter.com/generativist/status/1269043946786656257) whenever they have feedback about the company:
![](/media/2020-07-07/woloski.png)

## Invest in documentation and UI
You know your product, you know how it is meant to be used and you know what it shines at. To get users to see it, investing in good documentation and easy to understand UI is key.

Even something as _simple_ as "how to eat sushi" can benefit from good documentation.

A company I've always admired in this area (and others) is [Stripe](https://stripe.com/). Their [documentation](http://stripe.com/docs) and UI are extremely clear, and friendly for users. Just being on their site feels fun and exciting!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Achieving Alignment and Efficiency Through a Technical Strategy]]></title>
            <link>https://yenkel.dev/blog/achieving-alignment-and-efficiency-through-a-technical-strategy</link>
            <guid>https://yenkel.dev/blog/achieving-alignment-and-efficiency-through-a-technical-strategy</guid>
            <pubDate>Mon, 03 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Defining Auth0's technical strategy to better align teams.]]></description>
            <content:encoded><![CDATA[
_I've recently become a mentor at the [plato](https://www.platohq.com/) network. As part of that I've worked with them to write down some stories about my experience at Auth0. I thought it'd be interesting to share those stories in my blog as well. Originally published this one [here](https://www.platohq.com/resources/achieving-alignment-and-efficiency-through-a-technical-strategy-2008964066)._

# Problem
A common problem for fast-growing companies is "a lack of clarity", too many things are always happening at once. In our case, there was a lot of confusion about what was coming in the future and that made us slow and inefficient in making technological decisions. Teams were uncertain if they should be using a particular technology because they didn't know if that technology would be supported in the future, they were uncertain if they should be building a particular product in a certain way because they didn't know if that approach was aligned with our long-term technical strategy, etc. Obviously, this generated lot of inefficiency -- decisions were either made to be later revised or postponed because of insufficient information. This was happening across the organization affecting all teams and Engineers at all levels.

We believed we needed a long-term direction that explained how to approach the technical implementation of problems today and how to bridge the gap between our initial situation and the future vision. More precisely, we needed a documented technical strategy that would detail what we should and shouldn't be doing to be successful in the long run.

![](/media/2020-08-03/alignment.jpg)

# Actions taken
I started off by thinking extensively about the problem. I reached out to different people to better understand the reasons behind our slow decision-making. After talking to a great number of people I learned that all of them have been exposed to inconsistent information, and rumors, which made them afraid of making decisions, e.g. I heard the company is going for X in the future or I heard this particular technology Y is not going to be supported. A lot of confusion was caused by a particular rumor that we were going to support a certain customer need and its technical implications. People kept hearing about it, but concrete plans were never announced. I wrote down these issues, connecting all the dots and aiming to translate that information into knowledge. I realized we needed both short and term ways of solving the problem.

![](/media/2020-08-03/information-knowledge.jpg)

## Long term 
I came up with a set of topics that I believed the company needed to make decisions about. I tailored my presentations to suit two different audiences -- executive and technical. For the executive audience, I developed a succinct presentation, applying non-technical analogies and explanations, and providing actionable solutions. The technical presentation was much more detailed and included many technical terms. 

I used [nemawashi](https://en.wikipedia.org/wiki/Nemawashi) (an informal process of quietly laying the foundation for some proposed change or project, by talking to the people concerned, gathering support and feedback, and so forth) and shared with my VP of Engineering, other execs, my peers, and other senior leaders through to get buy-in before formally making a decision. More specifically, I approached people asking them for their thoughts and opinions securing the buy-in, so that by the time we met to discuss our decisions, they would be already in favor of the strategy. We finally met, discussed tradeoffs, and arrived at a set of decisions. All decisions were documented in a decision log and we committed specific owners -- in writing -- to carry them forward.

## Short term 
We had to fill the gap of uncertainty relating to some more urgent and short-term matters. Teams needed to make technical decisions and couldn't wait for a full-fledged technical vision and roadmap. We also realized that once we had that long term vision and decisions, there would naturally be the need to review decisions for specific exceptions. I put together a "design and architecture" (DNA) group formed by experienced engineers and established a process for teams and DNA to collaborate on designs. DNA also wrote guidelines and recommendations, including "approved" technology choices, to guide teams towards independent decisions that don't require review.

# Lessons learned
![](/media/2020-08-03/tree.jpg)
- The process of developing a strategy takes both time and patience. As engineers, we are often used to the short feedback cycle of coding whereas developing a strategy takes place at a slower pace and involves talking to and convincing a great number of people. The outcome itself is immensely rewarding, but it is also time-consuming and requires strategic thinking and a long-term focus.
- Secure buy-in before the decision-making meetings happen. Naturally, some decisions will be made in the meetings, but those should be tactical level decisions. Ensuring support from key stakeholders and people who are emotionally attached to the issue before the first meeting is of critical importance.
- Reviewing past decisions, even those that might seem "set in stone" is very important. In fast-growing companies, many things happen because of implicit understanding and inertia, not necessarily intentionally. Bringing those to light and challenging them is a part of growing and becoming more efficient.
- Customizing content for different audiences is a must. Executives would be perplexed if I would only talk about scale and performance internals, as much as engineers if I would only talk about the benefits of predictable costs.
- Document all the decisions and guidelines as clearly as possible explicitly outlining things that should and shouldn't be done. The strategy should also include the things that shouldn't be done as that equally helps teams to make their decisions.
- To scale decision making, provide teams with guidelines and recommendations for the most common things, and have a process to deal with exceptions.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Starting a Personal Mentoring Program at Work]]></title>
            <link>https://yenkel.dev/blog/starting-a-personal-mentoring-program-at-work</link>
            <guid>https://yenkel.dev/blog/starting-a-personal-mentoring-program-at-work</guid>
            <pubDate>Wed, 05 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Becoming a mentor and establishing a more formal personal mentoring program at work.]]></description>
            <content:encoded><![CDATA[
_I've recently become a mentor at the [plato](https://www.platohq.com/) network. As part of that I've worked with them to write down some stories about my experience at Auth0. I thought it'd be interesting to share those stories in my blog as well. Originally published this one [here](https://www.platohq.com/resources/starting-a-personal-mentoring-program-at-work-440115768)._

# The Problem
As a senior engineer, you are expected to help mentor more junior people. No one, however, teaches you how to do it. When you become a senior team member, junior engineers on your team are typically assigned to you for mentoring, and you usually help them within the context of the team, so at least the scope and people are clear. 

As a Principal Engineer I was not working on a specific team, but technically leading multiple teams. This meant I had to identify the people to mentor from various teams and figure out how to help them grow even when I might not have worked on their specific team or project.

![](/media/2020-08-05/mentor.png)

# What I did
When I became a Principal Engineer at Auth0 I fortunately already knew many people across many teams. To start, I picked two engineers from teams with whom I'd worked in the past since I was already fairly familiar with the problems they were likely encountering. I scheduled meetings with them every week for an hour to discuss their problems. I focused on the specific problems they were having first, not career aspirations, or (like a manager might do in a 1:1) happiness at work. Less experienced engineers would usually share a technical problem, while more experienced engineers would raise issues revolving around influencing, collaborating, and interacting with other people or teams.

Soon I was able to classify my mentoring based on three types of conversations I was having:

- A concrete, day-to-day topic. I need your help with this particular problem I'm having. While the problem could be both technical and non-technical it was nevertheless always very concrete.
- A specific, but more general topic. I am curious to learn more about how service X works or I would like to learn more about distributed systems. The mentee's interest in the topic not necessarily correlated with any particular project they were working on.
- A general career council/advise. I want to grow in my career -- what should I do? I would share tips and advice on how to move up the career ladder, cultivate your skills and competencies, etc.

![](/media/2020-08-05/growth.jpg)

After my initial efforts to become a mentor, I realized the full potential of establishing a more formal personal mentoring program within my company. I understood the importance of long-term mentoring and sometimes encouraged for more lasting relationships. 

- Every quarter I would determine how much time, depending on other projects, I would have available for mentoring. 
- Then I would target potential mentees by keeping my internal network updated and "keeping an ear to the ground". 
- Once I would identify people who I thought would benefit from my help, the initiative would be on me to approach them directly and offer to mentor them. 
- Also, I would leave a few briefer (half an hour) slots for some short-term on-demand mentoring. 
- Once the logistics were arranged, we could start with the sessions. 

The problems I have addressed in the past were either related to the specific problems within our company (how to improve incident response within our company) or to broader topics applicable across the industry (making distributed systems more reliable).

If someone aspired to learn more about a general topic, I would encourage them to research the topic in advance and come with questions before our first session. During our first session, I would try to set up the expectations and identify their knowledge gaps. Later, I would share a list of things that could help them improve and help them make priorities. We would also share books, articles, online content, etc. and discuss our readings of the previous week as we would be branching out to more specific issues and getting back to the original problem. 

If the person was more concerned about the specific project I would try to act as an advisor for that specific project. We would do weekly updates on the project and our discussion would usually have two aspects: technical and social (e.g. did you know that this or that person worked on a similar project before?).

# Lessons learned
- **Sometimes people come to you for mentoring and they don't know what they want to learn.** They might approach you asking to help them figure out "how to turn the oven on", but what they really want is to be able to do bake cakes. In those cases, it is essential to use the first session to understand what the mentee is looking to learn and agree on it with them.
- **Identify early in a mentoring session, which of the three types of conversations the session is starting off to be.** Know that it might change over the course of the session as you and the mentee talk more.
![](/media/2020-08-05/learn.png)
- **It is very important to be prepared for every single session.** If a person asks you about a specific project or topic and if you, time after time, fail to provide them with a good answer, you are probably not a good mentoring match. In that case, I would recommend my mentee to look for another mentor that can help them more.
- **Determining your mentoring time capacity in advance is very important.** Every quarter I assess how much time I have available considering how many projects I am a part of, and I determine my "mentoring budget". How many people I mentor that quarter and how often we meet is a consequence of that budget.
- **Keep your internal/company network up-to-date.** Know what is happening across the company, what new big projects are starting, what new senior engineers have been hired, etc. This helps you figure out who you should be helping, and you can reach out to those people to mentor them. Don't wait for them to reach out to you!
- **Generate internal demand for your skills, and knowledge** by regularly contributing to internal blogs, discussions, presentations, etc. This makes it more likely that people will be excited when you reach out to mentor them and that more people will reach out to chat with you.

# Conclusion
Mentoring is an important part of being a senior engineer as greatly it increases the impact you have on your organization. Whether you follow these aforementioned steps or others, the key is that you make time to mentor others, proactively look for opportunities to do so, and meet mentees where they are.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Balancing Multiple Assignments: Determine What Is Important in Each of Them]]></title>
            <link>https://yenkel.dev/blog/balancing-multiple-assignments-determine-what-is-important-in-each-of-them</link>
            <guid>https://yenkel.dev/blog/balancing-multiple-assignments-determine-what-is-important-in-each-of-them</guid>
            <pubDate>Thu, 20 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[How to balance multiple assignments, particularly when leading large projects while at the same time handling other day-to-day responsibilities.]]></description>
            <content:encoded><![CDATA[
_I've recently become a mentor at the [plato](https://www.platohq.com/) network. As part of that I've worked with them to write down some stories about my experience at Auth0. I thought it'd be interesting to share those stories in my blog as well. Originally published this one [here](https://www.platohq.com/resources/starting-a-personal-mentoring-program-at-work-440115768)._


# The Problem
As a senior engineer, you will likely technically lead one or more large initiative(s), while at the same time being entrusted with handling a great number of day-to-day responsibilities. As a result, you won't be able to spend all of your time and give your undivided attention to that one large initiative. You will have to determine how much time to spend on each different task and how to streamline your focus.
 
I ran into this problem as I was tech leading a feature we were building across multiple teams, while I was simultaneously immersed in my regular day-to-day responsibilities.

![](/media/2020-08-20/juggling.jpg)

# What I did
The success of the large initiative was critical for us at Auth0, this was a new product.

First and foremost, I identified the skills and competencies of all team members working on the large initiative. I considered their seniority, how long they had been with the company, and how familiar they were with the product. That allowed me to understand their strengths and spot the areas they might need help with. I also identified the critical things to get right. **From there, figuring out the focus areas is simple: the intersection between critical things and team skill gaps.**

For new products, we typically ship an HTTP API first, before the UI. Also, when starting new products everyone is eager to contribute ideas and "solve all problems". I decided to ensure that:

1. The HTTP APIs (our product interface) was aptly designed.
1. We wouldn't fall for scope creep.

![](/media/2020-08-20/important.jpg)

As a result, I decided to work very closely with the Product Manager (who was new to the company), as both scope and API priorities are things Product Managers own at Auth0. I met weekly with them to share context about the company and was available for questions.

From the very beginning, I was selective about what meetings to attend. If the team was working on scope definition I would make sure to attend, but if they would be discussing how to implement a particular feature, I would most likely not attend. The exception was meetings when we discussed functionalities that affected either the system as a whole or multiple teams. On the technical side, I did work a lot with the team on writing the design doc (RFC) after the proof of concepts were done, and also reviewing the implementation with them before our Early Access with customers started.
 
After a while, the initiative is progressing fairly well. The core parts of the implementation are in place, key decisions about scope and technology have been made, and scope and priorities are defined. I continue to work with the team and meet with them a couple of times a week, but I have been able to step back a bit more and focus on other initiatives.
 
# Lessons learned
![](/media/2020-08-20/bullseye.jpg)
- **As you grow you will have less and less time to entirely focus on a single project** and soon you will spread thin. In general, this is a natural consequence of climbing up the ranks; be aware of it and optimize your time accordingly.
- **When wearing a tech lead hat you are accountable for the technical solution**, even when you are spread thin. Prioritize how you spend your time to make sure the most complex, hardest to change parts are solved correctly.
- **Identify key inflection points in the project where your presence could make a difference**. I had to be around the team when we did a product discovery phase and when a large number of different ideas were floating around. That's a moment when people normally think they should try every idea and I had to help them differentiate what would be useful and what would not. I also helped a lot with HTTP API design decisions though it is something that a is closer to the Product Manager scope at Auth0
- **Make sure teams know you are there for them**. Even when I was working with multiple things simultaneously, I often checked in with the team leads --from both Engineering and Product. While I was not always present and involved in the tiniest of details, I was unequivocally clear that I was there for them, that I was listening to their feedback and that I would ensure that nothing was missing or delayed from my side.

# Conclusion
Juggling multiple assignments is a crucial part of growing as a software engineer. Figuring out what is important, prioritizing and being strict about time management are key ways of being successful at this.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to achieve career growth: opportunities, skills & sponsors]]></title>
            <link>https://yenkel.dev/blog/how-to-achieve-career-growth-opportunities-skills-sponsors</link>
            <guid>https://yenkel.dev/blog/how-to-achieve-career-growth-opportunities-skills-sponsors</guid>
            <pubDate>Tue, 25 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[How to define a model for career growth and apply it to get the right sponsors, improve your skills and maximize opportunities]]></description>
            <content:encoded><![CDATA[
I recently started mentoring someone that works at another company. Their goal is to become a "tech lead": at their company, this is a person that others look for technical advice, and that can influence teams' technical decisions. Because this person does not work where I do, I was forced to think generically about the matter of growth, rather than jumping to specific advice I would be able to provide a coworker.

In general, you might want to grow in your software engineering career, but:
- what does growth mean? 
- how can you achieve it?
- who decides if you are ready to grow?
- where do you start?

Years ago I read a phrase in [this article](https://www.forbes.com/sites/daviatemin/2016/04/04/what-theyre-saying-about-you-when-youre-not-in-the-room-and-what-you-can-do-to-influence-it/#4cb99ee771ac) that made many things click for me:
> The biggest decisions about your career are often made when you’re not in the room

For example, when I was working at a consulting company I did not decide which projects I was involved in. It depended on the contracts we closed, customers' budget and other's allocations.

Whenever I'm thinking about career growth I keep that in mind.  It helped me put together a mental model for professional growth. This blog post shares my growth model and how you can use it to carve your career growth path.

# The Growth Model
Let's introduce some terms first:

- Growth: access to more challenging and/or new opportunities. Growth is multidimensional.
- Opportunity: a possibility for improving and/or displaying your skills. They might be accompanied by financial rewards, recognition, etc.
- Skills: what you can do, including knowledge required to do it

From those three definitions a couple of questions arise:
1. Who are you displaying your skills to?
1. Who gets you access to opportunities?

To answer those questions and complete the model we need to define **Sponsors**:
- Sponsors: People that are aware of available opportunities and can grant them to you. 

Applying [systems thinking](https://lethain.com/systems-thinking/) to the model we come up with this diagram:
![](/media/2020-08-25/growth.png)


1. Your opportunities increase as new opportunities are granted to you. This rate depends on your sponsors.
1. Your skills improve depending on how fast you learn from your opportunities.
1. You get more sponsors the more people have a positive perception of your skills. These displays depend on your skills, e.g.: when you are given the opportunity to present you are displaying your presentation skills. If you are good at presenting, sponsors will perceive that.

## Takeaways
Our _growth_ definition means you want to maximize _your opportunities_. The most important takeaway is:

**Skill alone doesn't matter. If no one but yourself knows about your skills, you won't get any opportunities.**

What you want is to:

1. Maximize **Available Opportunities**
2. Maximize **Sponsors**

## Your energy
To keep the model simple and the post short I am not including "Your energy" as a stock. Modeling energy is complex:
When you take new opportunities your energy decreases. When you run out of energy you [burnout](https://medium.com/hackernoon/why-theres-so-much-burnout-in-software-and-what-to-do-about-it-4ef0297ca7cc).
When you do things you enjoy doing or rest (take fewer opportunities) your energy replenishes.
Your energy levels affect your skill learning/improvement rate.
And there are many ways in which your energy levels change that are not part of the system model I propose but impact the system nevertheless...

You can easily see how this would make the model more complex. However, just because it is harder to model it doesn't mean you shouldn't consider energy as part of your approach to growth.

# Available Opportunities
Opportunities come in different flavors, not all of them are "being tasked to do something". All of these are opportunities:
- Changing teams to work on a different problem set
- Being picked to technically lead an initiative larger than you have ever lead before
- Speaking at a conference
- Attending a workshop
- Frequently being mentored by a more senior person

![](/media/2020-08-25/opportunity.jpg)


If there are few **Available Opportunities**, it doesn't matter how good you are, it is very unlikely you will be granted new ones. **Available Opportunities** are also contextual: they depend on your seniority, team, company's financial situation, etc. You are also not interested in ANY opportunity. There are specific things that you'll be interested in doing and/or learning.

With those things in mind, these are some tips for maximizing **Available Opportunities**.

1. **Pick opportunities based on your growth goals**: If you want to grow as a distributed systems engineer, opportunities related to building mobile applications are likely to help you less than opportunities related to building databases. I recommend avoiding short term goals related to "titles" and instead prioritized improving your skills over time.

Goals don't necessarily need to be getting a better title/promoted. A goal in your career can just be "maximizing learning", which means you need to "maximize learning opportunities" and your "improve rate".

[This article](https://lethain.com/forty-year-career/) by Will Larson does a great job of explaining how to plan for a long term career.
[This article](https://medium.com/@bellmar/why-is-this-idiot-running-my-engineering-org-c6e815790cdb) by Marianne Belloti talks about some drawbacks of making career decisions based on just looking for higher titles and admiration


1. **Determine how to best get those opportunities**, ideally minimizing _"investment"_ required to get them: 
  
  If you can get the opportunities you are interested in by staying in your current team, that's great. If that's not the case: are there other teams in the engineering organization doing what you want? Are there teams in other departments in the organization doing it? If not, then it might be time to change companies.
  
  The same applies to conference speaking. If there are two similar conferences on the same date, and one of them requires you to fly 14 hours and the other one only 2 hours, you probably want to pick the latter.

  Large companies that have a strict process for granting opportunities based on just "years at the company" are reducing the amount of **Available Opportunities**, regardless of your skills. This is why high growth startups are sometimes so popular for people that want to grow, there are plenty of opportunities.

1. **Create your opportunities**: Proactively propose opportunities to sponsors, adding them to the **Available Opportunities** stock. 

  Want to get better at automated testing? Do some research to explain how more testing would help the team/company, explain that to the right sponsor (more on that later), and pitch to work on a project related to that next quarter. Simultaneously, reach out to someone in your organization that you believe is great at automated testing and ask them to mentor you.

## Reorganizations
Reorganizations might change the **Available Opportunities** a lot, especially at Senior Engineer (or higher) roles. Depending on the reorganization type and size you might get a heads up and be asked for feedback on options regarding where you will land. During those conversations consider the future **Available Opportunities** to decide what to do.

# Sponsors
Having determined the kind of opportunity you want, the next thing is to get the sponsors for those opportunities to think of your skills as a good fit for them. This involves:

1. Finding the right sponsor
2. Make your skills visible to them

## The right sponsor
When you begin your career as a developer, your team's Manager or Tech Lead is likely your main sponsor. They are aware of opportunities for tasks/work inside the team and they are the ones assigning work.

As you grow the situation changes, but you [always need sponsors](https://staffeng.com/guides/staying-aligned-with-authority). Senior Engineer role (or higher) related opportunities might be discussed at a cross-team level, maybe in a forum involving multiple Managers and/or Directors. Principal level engineers might also have a say in nudging decisions about critical initiatives. People's titles stop being a good indicator of "sponsorship ability". **In essence, you need to understand the [informal organization](https://en.wikipedia.org/wiki/Informal_organization) and how it relates to the opportunities you are interested in.**

If you are lost, ask someone you trust and is influential for help. This person doesn't necessarily need to be a coworker. They should be able to provide guidance. 

![](/media/2020-08-25/sponsors.jpg)


## Visibility
After identifying the right sponsor(s) you need to make your skills (and interest) visible to them ("skill displays"). Remember: this is not about "lying" or "faking it". This is about generating awareness. 

You can do this in different ways:
1. **1:1s**: if you can get a 1:1 with the sponsor to chat about opportunities, do it. In general, when you reach out to people asking them to help you grow and learn, their reactions will be helpful and positive. In these situations, it helps to [be self-aware](#self-awareness).
1. **Generate content**: internal or external content (conference talks, blog posts) allows you to share your skills. If you want more opportunities to work with Kafka maybe doing a Kafka brown bag and inviting the infrastructure tech leads can help.
1. **Share accomplishments**: The parallel to: "If a tree falls in a forest and no one is around to hear it, does it make a sound?" is "If you reduce AWS expenses by 25% but no one knows about it, did it happen?". Make sure the right sponsors know what you have achieved. Whenever you do this, make sure you give credit where credit is due.

### Sponsor attention
The more senior your sponsor the more things they have on their mind. It is hard for them to pay attention and keep in mind the skills and goals of multiple people. 

Make sure you provide visibility in an easy to consume format. There are some specific approaches that you can use to provide visibility about your work:
[Brag documents](https://jvns.ca/blog/brag-documents/) by Julia Evans
[Career narratives](https://lethain.com/career-narratives/) by Will Larson

Periodically remind sponsors of your skills and goals. Following up with your sponsors and repeating yourself once in a while is fine.

### Sponsor bias
Some potential sponsors might be biased. If they are negatively biased towards you, you will need a much higher "skill display rate" than a person they aren't biased against would need to get them to be YOUR sponsor. There might even be cases when they will never become sponsors, no matter how high your "skill display rate".

Lara Hogan has a [great blog post](https://larahogan.me/blog/what-sponsorship-looks-like/) on this topic.

Consider sponsor bias whenever you are looking to decide if a person is "the right sponsor" for you.

### Outside your company
Sharing your skills in public sites (LinkedIn, Twitter, conference talks, blogs, etc.) creates visibility for sponsors you don't even know to exist. Sometimes it is hard to say exactly what opportunities this might bring as the **Available Opportunities** stock in these situations is too large to reason about, but this is helpful.

## Self-awareness
Whenever you are going through this **your** perception of your skills ("self-awareness") is important.

- If you are trying to get someone to sponsor you for a job they don't think you are ready for, their perception of your self-awareness skill will lower.
- If you think you can do more than you actually can you will easily get frustrated as you will not get the opportunities you want.

Retrospect often. Be open to feedback. Camille Fournier has a great blog post on [asking for advice](https://medium.com/@skamille/debug-your-career-ask-for-advice-f0124c15837d) that can help.

For example, instead of asking someone "can you recommend me for X job?" ask "what skills do I need to improve on to be ready to do job X?". The latter makes it clear to the other person that you are open to feedback and it makes it easier for them to say "no". If they think you are ready for it, they will tell you as well.

# Sponsor yourself
The easiest way of getting an opportunity granted to you to sponsor yourself! This sounds weird, but this is essentially what you are doing whenever you use your time to learn a new technology or buy + read an industry-related book.

Being your sponsor allows you to take charge of your skill improvement without waiting for opportunities from others. While this requires spending your time on it (which is variably available to people depending on their context), this is a common predecessor to getting others to grant you opportunities related to that same skill.

After all:
> Luck is what happens when preparation meets opportunity

_Seneca_

---

Thanks to [Marianne Belloti](https://twitter.com/bellmar), [Will Larson](https://twitter.com/lethain), [Dirceu Pereira Tiegs](https://twitter.com/dirceu), and [Ramiro Nuñez Dosio](https://twitter.com/ramiro__nd) who reviewed this post and provided great feedback.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to influence people and get your items into their backlog]]></title>
            <link>https://yenkel.dev/blog/how-to-influence-people-and-get-your-items-into-their-backlog</link>
            <guid>https://yenkel.dev/blog/how-to-influence-people-and-get-your-items-into-their-backlog</guid>
            <pubDate>Wed, 02 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Describes a situation in which I influenced various stakeholders to get certain items teams' backlogs.]]></description>
            <content:encoded><![CDATA[ 
_ I've recently become a mentor at the [plato](https://www.platohq.com/) network. As part of that, I've worked with them to write down some stories about my experience at Auth0. I thought it'd be interesting to share those stories in my blog as well. Published initially [here](https://www.platohq.com/resources/eab418ba-ddd7-4d22-aa4f-1a044162343c)._
 
# The Problem
As a senior IC, you don't have a team of engineers. Instead, you will have to influence other people to make things happen. Your seniority helps provide some "respect" and a [halo effect](https://en.wikipedia.org/wiki/Halo_effect). However, you still have to make your case to Product Managers (PdMs), Engineering Managers (EMs), and execs. Sometimes what you believe would be beneficial is very different from their current priorities. They are accountable for their team's execution, while you are -- despite your seniority -- more of an influencer.

![](/media/2020-09-02/stakeholders.jpeg)

I was interested in having our teams work on a few reliability-related initiatives that I thought would be valuable for our customers. What I was lacking were engineers to make my ideas a reality.

# What I did
First, I looked at the data trying to grasp what the problem was and understand potential solutions. I analyzed past incidents, the overall state of our system, and customer tickets. I summarized the issue and tailored my message to different audiences: Product Managers (PdM) and Engineering Managers(EM), and executives/directors.
 
![](/media/2020-09-02/tailor.jpg)

When talking to PdMs to add my proposed initiative to the backlog, I said: "If you do this, you will have fewer interruptions and work on product items uninterrupted." Also, your customers will be happier because your product will be working all the time.
 
To EMs, I would usually explain how this would reduce reactive work and continuous fire fighting. It'd also result in a more stable product, which means that engineers are happier and more productive.
 
When engaging in conversation with executives, I would talk about brand damage, negative impact for the company, and how the system's reliability needs to be on par with other features. I borrowed a hugely persuasive argument from one of my peers: "reliability is the one feature that everyone uses. If our system is down, no feature is working".
 
Being aware that teams are usually time-constrained, I would pitch solutions in iterative steps, following the 80/20 rule. Instead of just throwing the problem at them, I proposed solutions that would dissect the problem into incremental parts. That way, they could make iterative progress and not consume most of their quarter. With a concrete plan in place, I met with each team and explained what we needed. I also told them I would be available for all of their questions throughout their work on the project.
 
# Lessons learned
![](/media/2020-09-02/meeting.png)
- Align your own goals with the organization's planning cadence. In our case, it happens quarterly. We discovered much of the problem close to the beginning of the planning cycle. Thus, we were a bit late with presenting it to the teams, which made it harder for them to include it in their backlogs. The sooner you can show the problem to teams, the better. You want to get to quarterly planning with them knowing about your important work.
- Whenever you talk about improvements to non-functional requirements, it is advisable to tie things to business outcomes and customers' needs. I framed the problem around faster and more reliable delivery, happier customers, and even potential upsell add-ons. I pitched a business case for the add-ons and provided an example longer-term roadmap. Attaching reliability improvements to tangible things like $$ makes it easier to make a case for them.
- Talk to all stakeholders separately. When lumped together, people tend to behave with a mob mentality and are more likely to resist changes to plans.
- Don't leave any of the stakeholders out. If anyone is missing, people will start to speculate why that is the case. That almost happened to me, but then I rushed to talk to a person that I thought I could omit.
- Don't just talk the talk, walk the walk. If something is important, make yourself available. I blocked time in my calendar to work on this, and reassured people that they could ping me anytime. If it wasn't important enough for me, I can't expect that it would be for them.
 
# Conclusion
Influencing stakeholders and teams is time-consuming and requires patience, but is extremely important as a senior individual contributor. The more successful you are at this, the more likely your ideas are likely to see the light of day.
 
If at first, you don't succeed, consider trying once more. Timing, audience-specific messaging, and emotional aspects play into the final decision whether to prioritize your work or not.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bridging Web 2 and Web 3: an identity perspective]]></title>
            <link>https://yenkel.dev/blog/bridging-web-2-and-web-3-apps-identity-perspective</link>
            <guid>https://yenkel.dev/blog/bridging-web-2-and-web-3-apps-identity-perspective</guid>
            <pubDate>Mon, 09 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[How can developers of Web 2 applications seamlessly use Web 3 constructs]]></description>
            <content:encoded><![CDATA[
_tl;dr: exploring how we can bridge the Web 2 and Web 3 ecosystems in the long run and how identity plays a big part in it._

I think Web 3 is here to stay. By Web 3 I mean the philosophy, concepts and technologies that prioritize user [choice](https://www.notboring.co/p/the-web3-debate?s=r) and [ownership](https://future.a16z.com/why-web3-matters/), and can be used to build decentralized services. [Blockchains](https://en.wikipedia.org/wiki/Blockchain) (e.g. [Ethereum](https://ethereum.org/en/), [Solana](https://solana.com/)), [tokens](https://ethereum.org/en/nft/), protocols (e.g. [IPFS](https://ipfs.io/), [TheGraph](https://thegraph.com/en/), [Lit](https://litprotocol.com/)), services (e.g. [ENS](https://ens.domains/), [Filecoin](https://filecoin.io/)), [dApps](https://ethereum.org/en/developers/docs/dapps/) and [users' keys](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs) make up Web 3 (not meant as an exhaustive list).

I'm unclear about how successful it will be, and I don't think everything around today will remain so. But I think it will be successful. I believe it's already successful for some things.

I also think that Web 3 is not "the only" web that will exist. It will co-exist with web 2, at least for some years (decades?). I'm not alone in thinking that:
[![](/media/2022-05-09/watanabe.png)](https://twitter.com/WatanabeSota/status/1494719525857927169)

[![](/media/2022-05-09/mulks.png)](https://twitter.com/lukemulks/status/1484752301969477635)

After that, maybe, another paradigm might come along. As a developer, and particularly a developer building products for other developers, I spend a lot of time thinking about what this will mean. I thought it might be interesting to share my thoughts in writing.

This post is mainly for
- devs building Web 2 apps that talk to Web 3 services
- devs building Web 3 services that you want to be consumed by Web 2 apps

_In this post, I link to Ethereum docs and concepts because I am most familiar with those, and it's the largest platform for devs today. Similar things apply to many other chains._

## Web 2 apps using Web 3 constructs
Web 2 apps can enhance experiences for users via Web 3 constructs.

Shopify is diving into ["tokengated commerce"](https://help.shopify.com/en/manual/products/digital-service-product/nfts#tokengated-commerce), customizing shopping experiences based on a user's NFTs. There's a very clear, in-depth article about this [here](https://www.notboring.co/p/tokengated-commerce). Tokengated commerce is a wonderful idea. What you own says many things about what you like. Customizing the shopping experience based on your NFTs feels natural.

Twitter and Stripe are partnering to allow [crypto payouts](https://stripe.com/blog/expanding-global-payouts-with-crypto), making it easy for content creators to get paid with cryptocurrencies.

Reddit is building its [community points system](https://www.reddit.com/community-points/) on top of a blockchain.

These are large consumer-facing platforms. They didn't become dApps, but they are dipping their toes into Web 3.

## What does it means for developers?
Developers will need to figure out how to integrate the Web 2 and Web 3 worlds. We are already starting to see this surface in different ways, but companies creating developer tooling and infrastructure are exploring and implementing Web 3 integrations: 
- [Stripe is building web 3 payments infrastructure](https://stripe.com/use-cases/crypto)
- [Auth0 announcing Sign in with Ethereum support](https://auth0.com/blog/sign-in-with-ethereum-siwe-now-available-on-auth0/)
- [Google Cloud is forming a web 3 team](https://www.cnbc.com/2022/05/06/googles-cloud-group-forms-web3-product-and-engineering-team.html)

The pattern: these large companies that build Web 2 development infrastructure are now creating components that make it easy for Web 2 app devs to integrate with Web 3 concepts ([NFTs](https://ethereum.org/en/nft/), cryptocurrencies, [ENS](https://app.ens.domains/), etc.) without going all-in (i.e. building a [dApp](https://ethereum.org/en/developers/docs/dapps/)).

They are building a bridge between Web 2 and Web 3 worlds. Their bridging is about allowing Web 2 developers to interact with Web 3 constructs, and that's the focus of this post. 

_Another aspect of bridging would be to make web 2 data available to Web 3 devs. I might do a blog post on that if this one spurs interest._

## The Web 3 trust model
Web 3 philosophy is decentralization. Each user owns their data, their $$, etc. 

[![](/media/2022-05-09/naval.png)](https://twitter.com/naval/status/1448089151677603846)

The Web 3 trust model relies on asymmetric cryptography, where the source of trust is the user's private key.

While there are some [delegation use cases](https://eips.ethereum.org/EIPS/eip-3074), third parties are commonly not trusted to act on behalf of users, and delegation would be a user's choice.

For a bridge between Web 2 and Web 3 to exist, trust about the user's address ownership has to flow in both directions.

## Identity is the bridge's fabric
Ultimately, the user's address in the context of web 3 is their "identity", who they are. Yes, they might have many of those, each being a separate "identity"/view that they present in different contexts. But it is their identity nevertheless.

Bridging the Web 2 and Web 3 worlds means solving identity on both sides of the bridge and making it easy for developers to build on top of that foundation.

Naturally, Web 3 principles should not be compromised when building the bridge. We might need to adapt the way Web 2 identity protocols (e.g. [OIDC](https://openid.net/connect/), [OAuth 2](https://oauth.net/2/)) and standards work to accommodate the Web 3 needs and philosophy.

## It all starts with an address
A Web 3 address has a related private key and public key. 

The number of addresses is growing fast:
![](/media/2022-05-09/address.png)

_[Ethereum Addresses](https://etherscan.io/chart/address)_

But the number of active addresses is growing slower:
![](/media/2022-05-09/active_address.png)

_[Active Ethereum Addresses](https://etherscan.io/chart/active-address)_

From the previous charts, we can infer that the percentage of internet users that actively use their Ethereum address is low. [Metamask said they have 30 million monthly active users](https://decrypt.co/95039/metamask-consensys-30-million-users) two months ago. But what of users that don't own an address?

For Web 3 to gain long-term adoption, a paved path has to exist for mass users to adopt it. Not everyone is crypto-curious. An approach that allows users to continue using the patterns they are used to (e.g. sign in with a social provider) and only become aware of blockchains (and keys) if they later want to is extremely valuable.

While the number of addresses is growing extremely fast, a relatively small % of all internet users solely own their private key: either creating the key pair offline or via a hardware wallet. A lot more exist as ["custodial wallets"](https://www.coindesk.com/learn/custodial-wallets-vs-non-custodial-crypto-wallets/), where services are the ones managing the keys. Centralized exchanges like [binance](https://binance.com/) or [coinbase](https://www.coinbase.com/) are the most common example. 

While that might not be "pure" from a Web 3/decentralization perspective, it is very positive. It's bringing some of the Web 3 ideas to the masses.

From a developer perspective, bridging the Web 2 and Web 3 worlds means custodial services have to associate blockchain addresses to user accounts, manage keys securely and provide control (at least for other internal development teams) to manage wallet interactions.

Services like [magic.link](https://magic.link/), [bitski](https://www.bitski.com/) and [venly](https://www.venly.io/) are helping to bridge the Web 2 and Web 3 worlds by creating key pairs for typical Web 2 login mechanisms and providing developers with APIs and UIs to manage those private keys.

Once a user controls a private key, that's where the fun begins :)

## Sign in with my private key
Let's look at a relatively simple scenario and see how it'd work in a Web 2 and a Web 3 application. The user:
1. Identifies on an app.
2. Changes their profile picture to \{input A\} and saves.
3. Realizes they made a mistake in #2.
4. Change their profile picture to \{input B\} and saves.

A Web 3 app (dApp) allows users to "connect" one of their addresses. This operation essentially gives the browser the user's blockchain address. There is no "backend" other than the blockchain and other decentralized services. Typically, operations that require authenticating the user on a Web 3 component require a signed message from the user's private key.

![](/media/2022-05-09/web3_auth.png)
_Web 3 case_

With Web 2 protocols, users don't have to take action to prove their identity on every operation. Users typically sign in once, and the client/browser stores a credential that is sent on subsequent requests to the backend, which uses it to authenticate the user.

![](/media/2022-05-09/web2_auth.png)
_Web 2 case_

_The diagrams above are oversimplified to get the point across_

The Web 2 user experience is better. Bridging the Web 2 world with the Web 3 world requires keeping a UX similar to the one from Web 2, and when calling the blockchain (or any other Web 3 native service)
proving the user controls the private key and intends to perform each specific operation.

How do devs associate the address with the user account as part of a Web 2 app? 

Services mentioned in the previous section already associate the private key with the user account. But what about those that don't? What if the user uses [Metamask](https://metamask.io/), [Argent](https://www.argent.xyz/), [Trezor](https://trezor.io/) or any other type of wallet? 

That's what [Sign-in with Ethereum solves](https://eips.ethereum.org/EIPS/eip-4361). It allows users to establish a session (in the Web 2 sense of the word) with a service, using their private key as a credential to prove ownership of the address.

![](/media/2022-05-09/siwe.png)
_Image source: https://auth0.com/blog/sign-in-with-ethereum-siwe-now-available-on-auth0/_

_If this sounds interesting, you should follow [@signinwitheth](https://twitter.com/signinwitheth) and the [@SpruceID](https://twitter.com/SpruceID) folks._

And once a Web 2 app knows a user's blockchain address for a fact, this opens up a world of possibilities.

## Potential use cases

Once the user's Web 3 identity is known, it'll be natural for Web 2 devs to want to go further. That will mean:

1. Reading/writing publicly available data (e.g. on-chain) related to the address and using it for business logic. Let's call these "operations that don't require user authentication".
2. Reading/writing data that requires authentication (e.g. a user's private video stored in decentralized storage or making on-chain transactions). Let's call these "operations that require user authentication".

Let's look at each of these in detail to understand how it could work.

### Operations that don't require user authentication
This one is the simplest case. Developers will be able to call any API that takes an address and does not require authentication. Some use cases that come to mind are:

- Reading [ENS](https://ens.domains/) or [Unstoppable Domains](https://unstoppabledomains.com/) to fetch profile data and display it, which would open up possibilities for a "global public username and profile pic" if users so choose to have it.

- Implementing [token gating](https://medium.com/@jshanks21/nft-meaning-token-gating-ad83aef7cccd) by fetching a user's [POAPs](https://poap.xyz/) and restricting access to resources based on them.

- Transfer assets TO a user's address on-chain.

- Down the road, if they become mainstream, use services like [proof of humanity](https://blog.kleros.io/proof-of-humanity-an-explainer/) to avoid fake user accounts.

Note that there are other ways to achieve some of these via digitally [verifiable credentials](https://www.w3.org/TR/vc-data-model/), and those don't require public data. But that's a story for another post...

[![](/media/2022-05-09/vcs.png)](
https://twitter.com/csuwildcat/status/1519379355691982849)


### Operations that require user authentication
Oh, things get tricky :) We are all used to a dialog like this:
![](/media/2022-05-09/consent.png)

If you want a Web 2 app to access your Gmail data, you log in with Google and then get a dialog to consent to the resources from your account you want the Web 2 app to have access.

How should this work for Web 3 services? If your Web 2 app wants to read data that exists in two different Web 3 services:
- should you have to "log in" to both of them? 
- or only consent to grant the app permissions to both of them? 
- what's the UX like in each case?

In the context of the Web 2 app, a token issued by an authentication server (Google in the previous example) is used to access Gmail's API (Gmail is the ["resource server"](https://www.oauth.com/oauth2-servers/the-resource-server/)). The Web 2 app sends that token on multiple calls to the API on behalf of the user. In the Web 3 services case, how should this work?
- should the user sign a challenge for each interaction with the Web 3 service? Not the best UX...
- should they delegate permissions to the app? how?
- how do Web 3 services need to adapt for these delegation scenarios?

The folks from Spruce have [started to think about these challenges](https://blog.spruceid.com/from-sign-in-with-ethereum-to-session-keys/) for some scenarios. I think that's a positive step forward. We need to learn about use cases and real-world scenarios to generalize those cases into repeatable patterns/guidance for all developers.

I think this is a big part of the challenge ahead.

# Conclusion
I'd love to know what you think about this because I am actively thinking and working on figuring this stuff out. As part of my team's work at [Auth0Lab](https://twitter.com/auth0lab), we are exploring how to bridge the Web 2 and Web 3 worlds, not in the context of just one app, but in the context of providing tooling for all developers.

If you have challenges, anecdotes, or use cases around this topic, I'd love to learn about them. You can [DM me on Twitter](https://twitter.com/dschenkelman) or [join the Auth0Lab discord](https://t.co/JRJtt04oDq), whatever you prefer. Let's build this bridge together!

---

Thanks to [Jose Romaniello](https://twitter.com/jfroma), [Tomas Soracco](https://twitter.com/toms0x), [Matias Woloski](https://twitter.com/woloski), [Patricio Worthalter](https://twitter.com/worthalter), and [Gabriel Gruber](https://twitter.com/GabrielGruber) who reviewed this post and provided great feedback.]]></content:encoded>
        </item>
    </channel>
</rss>