That I Would Be Good

Managing Technologists Through Life Events

Of all the topics I wish I had more training on as a first-time manager, handling difficult conversations and colleague life events is at the top of the list. Since taking over managing responsibilities for an awesome team of advocates, I feel more confident in leveraging my management experience, life experience and coaching training to support and grow people. That’s a fortunate position given that Unmind’s Closing the Leadership Skills Gap report reported that 84% of surveyed managers said they had received no formal training in people leadership skills.

 

Managing and supporting colleagues with empathy requires drawing on your own experiences. As a first-time manager in 2018, I wanted guidance, resources, and rules of thumb. After my 2024 miscarriage, I found some fantastic resources, such as this guide from the Miscarriage Association and this guide from Sue Ryder on bereavement support. But I still wanted some practical tips and knowledge from others that I couldn’t find. So here we are!

In this piece, I will outline the type of event managers may need to support colleagues. I’ll share practical tips on how to support them as a manager (and human) and tips for those going through it on handling working in tech through events and your recovery.

 

Content warning: this piece refers to upsetting topics, including loss and miscarriage. If these topics trigger you right now, feel free to skip straight to the Resources section at the end for organisations that can help and support you.

 

Event types

 

We need to stop thinking that upsetting events are something that you just deal with on personal time. The events we are talking about in this case are those that would be eligible for taking compassionate leave at short notice.

 

Types of unexpected events include, but are not limited to:

 

  • Loss of a close family member such as parents, children or other direct relatives. Many companies have dedicated bereavement leave entitlements for this type of event, albeit it may have stipulations on the relationship to the deceased. Some countries also have specific leave types, including the UK, where Statutory Parental Bereavement Leave was introduced in 2020.
  • Loss of other individuals in your life, such as extended family, grandparents or pets. These may not be covered by bereavement leave but could be eligible for compassionate leave, depending on your company policy.
  • Critical illness of yourself, a partner, or a close family member such as a parent or a child.
  • Life-threatening injury or illness.
  • Mental health challenges.
  • Divorce and separation.
  • Natural disasters or epidemics.
  • Miscarriage or child loss. Note that in the UK, stillbirth after 24 weeks of pregnancy comes under Statutory Parental Bereavement Leave introduced in 2020. They may also qualify for maternity leave in the case of stillbirth is covered in this video shared by the Miscarriage Association.

 

Guidance for all

 

All employees should be familiar with the company policies for compassionate and bereavement leave for your region and be able to search for local differences for your employees if a manager. It’s important to bear in mind that companies may have leave policies above the entitlement of the jurisdiction, so it’s important to also check your legal entitlement where you live. I was lucky that at Elastic, reading the policies was part of my initial training. It was at least in the back of my mind. I don’t remember having to read these policies as part of onboarding at prior employers, and I wish these policies were called out more.

You also need to ensure your bookmarks for these policies are current. In my panic, while going through my miscarriage, I wanted to check the entitlement, and in my panicked state, I found my bookmarks were out of date and struggled to find the new resources. Now, I ensure I have up-to-date shortcuts. Furthermore employers can also ensure these policies are available directly on intranet home pages and/or the documentation portal home.

 

Manager Guidance

 

For managers living in fear of a situation where you need to support a team member through one of these complex life events, don’t panic! In my experience of both sides, I’ve found the following tips have helped, and I’ve personally appreciated them while being supported by my own manager.

 

You may be surprised

 

These events are, by definition, unexpected. You may find some types of events, such as the bereavement of a colleague or a family member after a critical illness, may be expected, albeit still hurtful.

 

Take miscarriage as a particular example. As a manager, you may not even know your team member is pregnant yet. The NHS states that 3 in every 4 miscarriages happen before the 12th week of pregnancy. In the UK, you don’t need to notify your employer of your pregnancy until 15 weeks before the week the baby is due as per their pregnant employee’s rights. In my first pregnancy I waited as long as possible to tell my manager and HR because I didn’t want to be treated differently (which happened anyway similarly to those experienced and shared by Marharyta Nedzelska in her amazing talk).

 

In my case, I hadn’t told my manager I was pregnant yet, and worked from home through my symptoms until my miscarriage was confirmed by a scan just under a week later. He knew something was up as the team knew I had attended A&E as I let the team know (the emergency department for non-UK people). He probably knew it was still going since I cancelled a 1:1 twice. But I’m pretty sure he wasn’t expecting that news.

 

Another factor may be how it’s communicated. It’s not always going to be communicated verbally. A DM or email may be more appropriate if:

 

  1. You work in a global team with a manager located elsewhere.
  2. You may not be comfortable crying in front of your boss. It was hard enough telling my son, friends and family members this news without tears. Perhaps it’s my values and generation, but some cultures and generations may consider crying unprofessional.
  3. You may be in the middle of the situation and AFK (away from keyboard).

 

Considering these factors it’s safe to say you may be taken off guard when you receive this unfortunate news from your colleague. It’s ok to be shocked. If you have experienced a similar event in your life it may also be triggering. Both are ok!

 

Be a human 1st

 

Despite your surprise, it’s important to be a human 1st. This was the best advice I ever received from a mentor when I asked about handling delicate personal circumstances with direct reports as a newbie manager, and it remains relevant now. Manager as a term can seem odd as we’re supporting people and helping them manage their deliverables as part of a broader strategy, not resources, as we have the terrible habit of defaulting to in some corporate settings. Here you have a human going through an upsetting and unexpected event and has probably been handling it for longer than you realise.

At that moment, show support and ask them how they are. Listen fully and thoroughly to the answer. This is not the time to solve or fix anything, which many managers of a software engineering background may be tempted to do. Instead, ask open questions and coach the individual to see what possible help or adjustments they need. Possible adjustments could include:

 

  • Working from home (yes really!).
  • Adjusted hours, especially if they have follow up appointments or arrangements to make for events such as funerals.
  • Phased return to work.
  • Workstation adaptations (if suitable).
  • Time off to handle associated life admin. I certainly didn’t have any significant life admin, but in the case of bereavement, they may have will execution and estate wind-down responsibilities.

 

You may be worried about deliverables at this point. Time-critical deliverables may need to be delegated. For those following time-boxed ways of working, such as Scrum, this does NOT mean something due at the end of the current sprint must be picked up by remaining team members. In this circumstance, an incomplete story at the end of the sprint should not be your priority at this precise moment. Consider if managing stakeholder expectations and carrying the work is more appropriate.

 

Remember that absences raised in internal systems can be backdated. Remind them of the procedure to mark the absence, and advise them to either add it when they can or offer to add it on your side if possible. In both my and my husband’s case (he experienced the loss too of course), we already had annual leave booked. Changing the leave classification, in this case, is essential as it gives your employee back the time to legitimately rest later (more on why in the employee section covered later).

 

Ask for help

 

The first time you handle one of these compassionate events as a manager, it can feel intimidating. Learning to lead and support people is scary enough, as people feel more breakable than code. And this is a potentially vulnerable person!

 

You may also be unsure what adjustments you can offer this person, if their adjustments are reasonable and can be supported, or which type of leave the event qualifies for. If the policy is still unclear, contact HR for guidance via the correct internal channels if needed. Also, ensure that any follow-ups you do are remediated and promptly communicated to the individual.

 

I would also recommend following up to HR to see if they have any specific policies covering this type of event in addition to compassionate leave policies. Some companies may have specific policies outlining support for specific events including miscarriage, bereavement and critical illness.

 

Express condolences as a team

 

Marking condolences with flowers or cards is common in many cultures (although not all which should be considered), and in that case, should extend to colleagues. Some companies have procedures to automate the sending of flowers or cards centrally. Others rely on managers to organise more ad-hoc activities, both of which are ok.

It’s important to send them at the right time. Both my husband and I were appreciative of the flowers and cards we both received from colleagues after our loss. I was also grateful my colleagues also gave me a gift to help me recuperate (💜). Both teams also sent them after we had returned home from our travels. Particularly for those having to travel for a bereavement and cultures that hold funerals and burials within a few days, the last thing you want is for the delivery not to be received, or indeed your colleague coming home to dead flowers!

 

It happens! However, in my case, it was a relative rather than colleagues that sent flowers while we were away.

 

The usual reward processes don’t stop!

 

These events can strike at any time. Including around the time of key deadlines such as submission of promotion cases. This highlights the importance of regular career conversations and documentation of key evidence for promotion cases. If that individual is unexpectedly away for a compassionate event, you can’t ping them for help with the evidence. Or worse, I’ve heard stories of friends who have had to complete their case paperwork because their boss claimed to be “too busy”. In that case, a compassionate event could delay their promotion to the next cycle.

 

My experience was excellent (given the circumstances) in that I returned to my case being submitted while I was out. Of course, legal protections exist in many countries to prevent discrimination on protected characteristics such as pregnancy, including in the UK where I reside. Albeit it felt challenging to celebrate an achievement after a moment of despair and loss, I was relieved that I hadn’t missed the opportunity.

 

Still, celebrate events

 

Sadly, it’s the case that some types of celebratory events can be triggers for those who have experienced loss or disappointment. I remember in my prior company seeing the looks of disappointment of those who missed out on promotion when others were celebrating their promotion day. For those who have encountered pregnancy loss or fertility struggles, seeing another’s pregnancy thrive or hearing others’ good news can be a reminder that that is no longer you. Just like those going through separation or divorce may struggle to hear about a colleague’s wedding plans.

I’ve discussed with friends that this presents a conundrum as to whether you celebrate in those instances. And in that case, I say a strong resounding yes. Of course, be that listening ear for those colleagues who will struggle for a moment and may need a sounding board. But I would never want to see teams not celebrate wins in those regards or share gifts for impending arrivals. It shows me how much more critical sharing and celebrating those moments is.

 

Colleague Guidance

 

While providing a resource for managers was the aim of this piece, it would be a missed opportunity to share some advice for those going through a compassionate event who may want advice on handling their situation. Here, I evaluate the techniques that did and sometimes didn’t work for me.

 

Have leave policies bookmarked

 

As stated previously in the Common Guidance section, ensure you know your current company’s leave policies in your location from your start date and have it bookmarked for easy access. Furthermore, update your bookmarks if your documentation systems are changed or migrated.

 

This advice comes from direct experience. While going back and forth to the hospital, being pinged between different services, and hours spent on the phone trying to get assistance, I wanted to remind myself of whether compassionate leave applied to my case if I was confirmed as having a miscarriage. In my panic and frustration (yes I’ll admit it), even someone familiar with search struggled to find the documentation. It can happen to anyone.

 

While it’s not urgent or comfortable, make sure you know your company’s compassionate leave policy and your local and legal entitlement.

 

Don’t be a meeting martyr

 

Be kind to yourself and cancel meetings until your news is resolved. In some of these situations, you may be awaiting news in an anxious state while still working in the background. Having some aspect of your everyday routine and working on solo tasks such as coding, code reviews, and admin can be valuable and helpful distractions. For me, they were. However, when it comes to meetings, I should have just declined them earlier.

 

Confirmation of my non-viable pregnancy took 6 days from my initial symptoms, 3 of which were working days (thanks to a lUK bank holiday). I was bounced between different services while using work as a welcome distraction at that time. But I had 2 1:1’s and a team call that I had to decline at the last minute. I, as a stickler for timekeeping, hated doing it, so in hindsight I wish I had cancelled earlier.

 

Being in DevRel and speaking at events, you may need to cancel conference engagements or travel. I did. Even considering that my urgent medical appointment got moved up (leading to a frantic dash by my husband across London to get to the hospital with 2 hours notice), I would not have been in the right headspace to present.

It doesn’t matter if you’ll be back from the hospital in time and can juggle around it. In my case, I found medical practitioners are just as optimistic as Fred Brooks thought programmers are as covered in the seminal text The Mythical Man Month. Sadly their optimism didn’t alleviate my anxiety. It might be that everything is ok, and it isn’t bad news. But take a moment to think of your mental state after that news. Even if it’s positive news, you may need decompression time.

 

To be safe, decline the meeting and focus on your headspace instead!

 

Take your entitlement*

 

You may consider that not taking your compassionate leave shows that you’re strong and resilient. Particularly for Brits like myself, who, with our stiff upper lips in the air, live by the ethos of “keep calm and carry on”. Particularly if you already have planned time off as I did. While routine can be a useful aid in handling grief, you should never feel forced to push through the routine.

 

Refusing your time doesn’t show your resilience. At my follow-up scan where the nurse confirmed my miscarriage had completed, I requested a doctor’s note for 2 days sick to cover the medical appointment days before I went on vacation. Cue a very confused doctor appearing, asking why I only needed 2 days (2 weeks is the standard). I confirmed that we were already on annual leave from work, and I only wanted coverage for the working days. To which he advised that I should have that leave converted to sick or compassionate leave for use for legitimate rest at a later date.

 

I mean… he had a point. It wasn’t a restful holiday. I remember my heart breaking as I told my son that he wouldn’t be a big brother, giving him a cuddly toy to remember the baby. I was still miscarrying and cramping while sitting on the couch with heat and pain relief at a relative’s home. Personalisation and permanence, as per Seliman’s 3 P’s of Resilience, were rolling rife through my brain as I blamed myself for being defective and thinking my grief would last forever. Not taking the leave doesn’t make you strong. Instead, powering through can leave you weak and struggling at work.

 

Software systems can be changed. That annual leave can be added back to your entitlement and replaced with compassionate leave. In my case, I raised an HR request and had it actioned very promptly (as per the advice for managers from the prior section). Although my husband’s request took a little longer, he too got his leave changed to compassionate leave instead. Many systems allow you to make a request, but if you are in doubt (or panic, as in my case), just ask!

 

Grieving doesn’t only happen on personal time

 

When you do return to work, you will still be grieving. Processing a loss takes months, not just the 2 weeks you take for compassionate leave. Some people struggle returning to work, while others like me may find that the work routine is helpful. Even when you return to work, grief doesn’t fit nicely outside working hours.

 

I was lucky that I had wonderful supportive colleagues who asked me how I was doing, and listened fully and compassionately to the answer and didn’t shift awkwardly if my voice broke as I spoke. I had similar experiences to Sheryl Sandberg, which she outlines in her book Option B: Facing Adversity, Building Resilience and Finding Joy, where sometimes I did find some people didn’t quite know how to talk to me about what happened or what I was going through. Thankfully that wasn’t my colleagues!

 

For a while after, I experienced what I (affectionately, not dismissively) call “Wobbles”. Sheryl refers to them as Crying Breaks. Sometimes, these moments of sadness would come out of the blue, meaning I had to take a minute. Quite often, they were triggered by external factors, such as:

 

  • Seeing pregnant women or newborns out and about.
  • Reminders of previously cancelled medical appointments related to my pregnancy. As a software engineer, this system limitation leaves me particularly irritated as I know it’s possible.
  • Social media adverts on baby items that persisted even after scrubbing my settings (and according to this BBC article I’m not the only one).
  • News of others in my life being pregnant (but never in a way that I would never want to congratulate them).
  • A UK election freepost circular put through my door that had a picture of an unborn fetus on the front. Don’t worry it was promptly ripped up and put in the outside bin as I didn’t even want it in the house.
  • Songs about loss playing on my playlist.

 

I am fortunate enough to have the option to work from home if I’m not at an event. When I had a wobble at home, I could take a break from my desk or switch off my camera on calls as needed.

Sadly some triggers appeared in the office too, which can be more difficult to escape. On my second day back at work I was hosting a meetup in the office and got chatting to a lovely attendee who was transitioning back into work after finishing her second stint of maternity leave. It was definitely not her fault, and I was happy to chat about experiences based on my own maternity leave return some years earlier with my son. But I won’t lie, that was an emotional sucker punch.

 

Be aware of potential spaces that you can duck into for an unexpected break in the office, conference venue, or any area you are working in. Be on the lookout for wellness spaces, empty meeting rooms, or even a spare toilet stall at a pinch.

 

Don’t let work be an escape

Don’t feel guilty about adapting or moving deliverables around when you start back to make them manageable. There is a fine line between establishing a regular working pattern with achievable deliverables as a routine, and using work as an escape from your grief.

 

When I came back to work, I was angry at myself as my code demos and new talk that was due for a conference in a few weeks was nowhere close to where I wanted it. I confided in a friend about how far behind I was and they had some great advice. Through coaching I managed to form a plan of what I could get working, and then adapted the talk to authentically lean into the failure (in this case, my custom ML model couldn’t find the cake). It’s now a talk that many people commend me on for being relatable, that I am proud of, and that reminds me that I’m human too.

 

This advice is not just for the weeks following a loss. I should have also followed this advice a few months later on the month where I would have been due. Key events such as the first holidays and milestones following a loss can be just as hard as the weeks after. Because they are different to what you feel they should have been. I would have been due in a month that is busy for DevRel due to the sheer number of conferences running. Therefore, my brain told me to keep busy and have a ton of conferences in my schedule. Rather than being a helpful regular routing, I found the travel and lack of flex in my schedule made handling grief hard. Almost as if I was running away from the problem.

 

Be mindful of those times where you expect to have wobbles, and be kind to yourself. In those moments I ensured I followed my own advice regarding my social battery, specifically retreating to my hotel room to recharge in the evenings if needed.

 

Conclusion

 

In this piece I’ve discussed the challenges managers and colleagues face in compassionate events, presented the types of event where compassionate leave should be applied, and shared tips from my own experiences on how to handle them as humans. If you have read to this point I commend you! Discussion of these topics is hard, and therefore important to share.

 

I’m glad to report that I’m now doing well, and wobbles are very rare. Grief does ease over time, and you build resilience. I am lucky that I had wonderful support from friends, family and colleagues.

It’s also important to mark those events to help resolve them. One of the best things we did was apply for a Baby Loss Certificate and a Christmas decoration for our tree to ensure their time was marked.

 

If you’re struggling, or want help and guidance for a difficult event, check out the below resources, or use them to find equivalent organisations in your area. Take care!

 

Thanks for reading!

 

Help & Resources

If you’re looking for more resources or organisations to support you at a difficult time, check out the below resources. These are UK specific, but have useful guidance and could give you an idea of how to search for organisations in your area. Please note this is not an exhaustive list and there are many wonderful organisations out there to help.

 

Miscarriage and Child Loss

 

 

Bereavement

 

 

Critical Illness

 

 

Mental Health

 

 

Divorce & Separation

 

 

Natural Disaster and Epidemic Support

 

Is it (F)ake?!

Image Classification with TensorFlow.js and JavaScript

I am not a machine learning expert! But I am a big fan of baking shows. Driven by hunger and jealousy at the skill of the featured bakers, my son and I regularly watch baking shows. Our favourite is the nail-biting Is It Cake?, where judges must find the ultra-realistic cake hidden among the decoy objects.

3 pedestals, 1 cake (Credit: Netflix)

Over 3 seasons I have vastly improved my cake-finding skills. But I’ve always wondered if a model could do better. Join me as I show how to extract images from web pages with JavaScript using Playwright and Unsplash to Elasticsearch, and learn how to use TensorFlow.js, a JavaScript machine learning library, to figure out if models or humans are better at finding the cake!

 

Data Sourcing

 

Irrespective of whether we use a pre-built model or train our own, we need images of both cakes and not cakes for this exercise. In this case, 2 sources of data were used that are discussed in the subsection sections.

 

Cake Image Gathering

 

For the cakes I used a list of sites I extracted from the Netflix blogs that introduced the bakers for each season, such as this one for season 1.

 

From these sites, I was able to pull out the src URL of each image using the JavaScript implementation Playwright, an E2E testing and automation framework maintained by Microsoft. I’ve been fortunate to use Playwright in some of my projects at work in recent years, building on my prior experience using Cypress.

 

The logic utilises a reusable page object to load each URL in turn. Within each page, the generic locator is used to find all <img> tags and extract the src attribute of each.

 

const { firefox } = require("playwright");

async function getCakeImages() {
  let browser = await firefox.launch();
  let page = await browser.newPage();

  // Utility loads the cake sites JSON file using fs
  const cakeSites = loadCakeSites();
  let imageUrls = [];

  for (site of cakeSites) {
    console.log(`Extracting image urls for site: ${site.url}`);

    try {
      await page.goto(site.url);
      const currentPageImages = await page
        .locator("img")
        .evaluateAll((images) =&gt; {
          return images
            .map((image) =&gt; {
              return image.getAttribute("src");
            })
            .filter((url) =&gt; {
              // Ensure we have extracted the src attribute 
              return url != null;
            });
        });
      imageUrls = imageUrls.concat(currentPageImages);
    } catch (e) {
      console.error(`Unable to get images for site ${site.url}`);
    }
  }

  // Persist image URLs to storage for reuse in classification
  await writeUrlsToFile(imageUrls, "./scripts/cake-image-urls.json");
  await browser.close(); // Tidy up after ourselves
}

 

In addition to the key extraction logic, notice that we persist the URLs to cake-image-urls.json. Let’s be a good web developer and avoid repeatedly scraping the business sites of these awesome bakers, shall we?

 

This approach gave me 367 images of cakes to work with. Although there are some limitations to this dataset such as the inclusion of logos and biscuits, we have a good data set to start with. Sweet!

 

Not Cake Image Sourcing

 

For the opposing category, we need several different types of objects. To mirror our favourite cake show, these should be objects that we have replicated in our cake samples. I had a set of terms I had extracted based on the cakes I had found. But the question was how to get images for each of these terms easily.

 

For this problem, the Unsplash Developer API is a great resource to get royalty-free images matching a simple query. I used the /photos/random API endpoint to obtain a set of random photos for each query. I didn’t even need to resort to native calls as there is a JavaScript wrapper that can be installed easily in your project:

 

npm install unsplash-js

 

Once installed in my project, I used the API key I generated as part of the process of registering a new account and creating a test application to instantiate an instance of the client:

 

const { createApi } = require("unsplash-js");

const client_id = process.env.UNSPLASH_ACCESS_KEY;
const unsplash = createApi({
  accessKey: process.env.UNSPLASH_ACCESS_KEY
});

 

Once connected, the getRandom method allows for an image count and query to be passed as part of the payload to give back a set of random images that match the query:

 

// A sample set of queries, not the full set
const queries = [ "cup", "vase", "candle", "bottle", "plate", "tray", "thimble" ];

async function getUnsplashImageUrls() {

  let imageUrls = [];

  for (query of queries) {
    try {
      const response = await unsplash.photos.getRandom({
        count: 10,
        query: query
      });

      const responseUrls = response.response.map((result) =&gt; {
        return result.urls.small;
      });
      imageUrls = imageUrls.concat(responseUrls);

    } catch (e) {
      console.log(`Unable to get images for keyword ${query} from Unsplash`);
    }
  }

  return imageUrls;
}

 

Unsplash provides access to images in several sizes as part of the result.urls object. The small image size was suitable for both showing the image in my game and for the model classification stage.

 

One gotcha to be aware of when using a test application rather than a production application in Unsplash is there is a request limit of 50 requests per hour. Through batching, I managed to get 174 images of various non-cake objects, but I did lose a few along the way.

 

Pre-built Models

My prior experience with machine learning is through vector search, where I have used pre-build models to generate vectors from text to build semantic search solutions. To ease the steep learning curve for myself it made sense to start with existing models and assess their capability to find the cake.

 

Looking at the pre-trained models available via TensorFlow.js, I settled on 2 vision models that looked suitable for my use case.

 

  1. COCO-SSD: an object detection model. SSD, or Single Shot MultiBox Detection, is a type of model that can identify multiple objects in an image. COCO in this model name refers to the dataset Common Objects in Context on which the model was trained. It can detect 80 different classes of objects.
  2. MobileNet: MobileNets are small, low-latency, low-power models that can solve a variety of use cases. They are commonly used for classification and detection use cases, as well as for generating feature embeddings for different types of data. MobileNet is trained on the ImageNet image database.

 

Initially, I did manage to get a simple in-browser implementation working based on a simple img HTML element and the steps in this webcam tutorial from Google Developers, as evidenced from this commit. However, I had to abandon this approach and switch to generating classifications in a Node.js and Express server due to CORS error hell (sigh). What was important to my solution was having classifications at all, and them being calculated at the time in the browser was a bonus.

A person cutting a beautiful cake

Let’s see how we can classify the above image with each pre-built model using the tf-node backend.

 

Image Conversion

With the move to Node.js, I no longer had access to an img element on which to generate the predictions. This meant that the images needed to be preprocessed into a tensor, AKA a multi-dimensional array of a uniform type, to be consumed by the model.

 

For this, the approach was to create an 8-bit unsigned array from the buffer obtained when we get the image URL:

 

async function getTensorFromImage(imageUrl) {
    try {
      let response;
  
      if (imageUrl.includes("unsplash")) {
        response = await getUnsplashImageSource(imageUrl);
      } else {
        response = await getImage(imageUrl);
      }
  
      const buffer = response.ok
        ? new Uint8Array(await response.arrayBuffer())
        : null;
  
      if (!buffer) {
        return;
      }
  
      return tf.tidy(() =&gt; {
        const decodedImage = tf.node.decodeImage(buffer, 3);
        return decodedImage;
      });
    } catch (e) {
      throw Error(`Unable to create tensor for image ${imageUrl}`);
    }
  }

 

The function tf.node.decodeImage converts the buffer response to an image, with the channel count of 3 denoting an RGB image. TensorFlow.js creates intermediary tensors as part of many processes, and you may also create a few yourself. To tidy things up, wrapping logic in a tf.tidy call is a good idea for housekeeping purposes. Note that tf.tidy only supports synchronous operations, meaning for async logic tidying up using tf.dispose or tensor.dispose will help you tidy up after yourself.

 

COCO-SSD Predictions

 

To use any pre-trained model out of the box, including COCO-SSD, we need to load the model, transform the image to a tensor and generate the predictions. The example code, using the helper function getTensorFromImage discussed above, is as follows:

 

var tf = require('@tensorflow/tfjs-node');
var cocoSsd = require('@tensorflow-models/coco-ssd');

function getPredictionsFromCocoSsd(imageUrl) {
    const model = await cocoSsd.load();
    
    const tensor = await getTensorFromImage(imageUrl);
    let predictions = [];

        if (tensor &amp;&amp; model) {
            predictions = await model.detect(tensor);
        }

    res.send(JSON.stringify(predictions));
}

 

Given we are running a detection algorithm, calling model.detect will give us the predictions for the image, including the position of the bounding box containing each image, similar to the below:

 

[
  {
    "score": 0.9078599214553833,
    "class": "cake",
    "bbox": [
      31.88125991821289, 85.59701451659203, 120.83561384677887, 236.453576952219
    ]
  },
  {
    "score": 0.8294360637664795,
    "class": "person",
    "bbox": [
      129.78285256028175, 75.89923804998398, 181.74191591143608,
      271.4830951690674
    ]
  }
]

 

MobileNet Classifications

 

The code leveraging MobileNet compared to COCO-SSD is very similar. The need to load the model and output the generated predictions is not different. As you’ll see in the below snippet, the only change is that we use model.classify to generate the image classifications rather than invoking model.detect as we did before:

 

var tf = require('@tensorflow/tfjs-node');
var mobilenet = require('@tensorflow-models/mobilenet');

function getClassificationsFromMobileNet(imageUrl) {
    const model = await mobilenet.load();
    
    const tensor = await getTensorFromImage(imageUrl);
    let predictions = [];

        if (tensor &amp;&amp; model) {
            predictions = await model.classify(tensor);
        }

    res.send(JSON.stringify(predictions));
}

 

With our sample image, the results are simply a set of class names with the probability of their existence within the image:

 

[
  {
    "probability": 0.33521249890327454,
    "className": "shower curtain"
  },
  {
    "probability": 0.19605109095573425,
    "className": "iron, smoothing iron"
  },
  {
    "probability": 0.04750530421733856,
    "className": "tub, vat"
  }
]

 

Persisting Results

 

For both sets of results, storing the images is important to allow players of the Is it (F)ake?! game to see how they compare to the models. For this reason, I indexed the results with the image URL and category to the classifications index. Once the connection is established, we add the document using client.index.

 

const { Client } = require("@elastic/elasticsearch-serverless");

const index = "classifications";

const esClient = new Client({
    cloud: { id: process.env.ELASTIC_CLOUD_ID },
    auth: { apiKey: process.env.ELASTIC_API_KEY },
  });

async function addClassifiersToIndex(url, category, mobilenetClassifications, cocoSsdClassifications) {
    const imageDocument = {
        image_url: url,
        category: category,
        mobilenet_classifier: mobilenetClassifications,
        coco_ssd_predictions: cocoSsdClassifications,
        my_model_classifier: null,
      };

    return await esClient.index({
      index: index,
      document: imageDocument,
    });
}

 

For anyone wondering about the library import @elastic/elasticsearch-serverless, I used the preview of Elasticsearch serverless for this project. If you are aiming to persist results using an existing Elastic Cloud or local installation, please install @elastic/elasticsearch to your project instead.

 

Building My Own Model

 

The question remains as to whether I could build my own model to find the cake. TensorFlow.js provides two different types of layered models:

 

  1. Sequential models, where the output of one layer is the input of the next. These can be created using tf.sequential().
  2. Functional models created using tf.model() that allow for the creation of an arbitrary graph of layers. These models must not include cycles.

 

Inspired by this blog on dev.to I decided to create and train my own Convolutional Neural Network, or CNN to classify the images.

Convolutional Neural Network Diagram | Source: What is Convolutional Neural Network

As depicted in the above diagram, these models contain 3 distinct types of layers:

 

  1. Convolution layers where a filter (or kernel, basically a matrix of weights) scans the image to identify features of interest in the image, utilizing the ReLu function.
  2. Pooling, or downsampling, layers that reduce the dimensionality of the preceding convolution layer to limit overfitting, reduce complexity and improve efficiency.
  3. A fully connected layer classifies the image using the features extracted from the convolution layers, producing a set of probabilities that the image fits the classification using the softmax function.

 

Combining a lot of reading and the aforementioned blog to classify cats and dogs, I ended up with the below model:

 

// Convolutional Neural Network (CNN) example
function createModel() {
  const model = tf.sequential();

  /* Creates a 2d convolution layer. 
   * Concept from computer vision where a filter (or kernel or matrix) is applied and 
   * moves through the image by the specified strides to identify features of interest 
   * in the image 
   * See https://www.kaggle.com/discussions/general/463431
  */
  model.add(
    tf.layers.conv2d({
      inputShape: [IMAGE_WIDTH, IMAGE_HEIGHT, 3],
      filters: 16, // dimensions of the output space
      kernelSize: 3, // 3x3 matrix
      activation: "relu", //f(x)=max(0,x)
    })
  );

  /* Max pooling reduces the dimensionality of images by reducing the number of pixels 
   * in the output from the 
   * previous convolutional layer.
   * Used to reduce computational load going forward and reduce overfitting
   * See https://deeplizard.com/learn/video/ZjM_XQa5s6s
  */
  model.add(
    tf.layers.maxPooling2d({
      poolSize: 2,
      strides: 2,
    })
  );

  model.add(
    tf.layers.conv2d({
      filters: 32,
      kernelSize: 3,
      activation: "relu",
    })
  );

  model.add(
    tf.layers.maxPooling2d({
      poolSize: 2,
      strides: 2,
    })
  );

  // Flattens the inputs to 1D, making the outputs 2D
  model.add(tf.layers.flatten());

  /* The Dense Layer is a simple layer of neurons in which each neuron receives input 
   * from all the neurons of the previous layer, 
   * thus called as dense. Dense Layer is used to classify images based on output from 
   * convolutional layers. 
   * See https://towardsdatascience.com/introduction-to-convolutional-neural-network-cnn-de*/
  model.add(
    tf.layers.dense({
      units: 64,
      activation: "relu",
    })
  );

  model.add(
    tf.layers.dense({
      units: CLASS_NAMES.length,
      activation: "softmax", // turns a vector of K real values into a vector of K real values that sum to 1
    })
  );

  model.compile({
    optimizer: tf.train.adam(), // Stochastic Optimization method
    loss: "binaryCrossentropy",
    metrics: ["accuracy"],
  });

  return model;
}

 

Once defined, I created a tensor representing the images, and another with the corresponding labels:

 

const CLASS_NAMES = ["cake", "not cake"];

// Get a subset of the cake images from Elasticsearch
  const cakesResponse = await getFirstNImagesByCategory(CLASS_NAMES[0], 50);
  // Resize and transform the images into tensors
  const cakeTensors = await getTensorsForImageSet(cakesResponse);

  // Get a subset of the Unsplash images for not cake images from Elasticsearch
  const notCakesResponse = await getFirstNImagesByCategory(CLASS_NAMES[1], 50);
  // Resize and transform the images into tensors
  const notCakeTensors = await getTensorsForImageSet(notCakesResponse);

  const images = cakeTensors.concat(notCakeTensors);
  const labels = Array.from({ length: cakeTensors.length })
    .fill([1, 0])
    .concat(Array.from({ length: notCakeTensors.length }).fill([0, 1]));


  // Randomize images and labels to prevent order bias while maintaining correlation  
  tf.util.shuffleCombo(images, labels);
  // Create a single tensor from the tensor array
  const singleImageTensor = tf.stack(images);
  // Create a single tensor of the labels
  const labelsTensor = tf.tensor2d(labels);

 

The utility function getTensorsForImageSet uses similar logic used to get the image from the CDN and convert it to the tensor. The sole difference is that we resize the generated tensor using tf.image.resizeBilinear.

 

To train the model we use model.fit, specifying the corresponding image and tensor labels alongside the required parameters:

 

const BATCH_SIZE = 32;
const NUM_EPOCHS = 10;

await model.fit(singleImageTensor, labelsTensor, {
    // Number of samples to work through before updating the 
    batchSize: BATCH_SIZE, internal model parameters
    // Number of passes through the dataset
    epochs: NUM_EPOCHS, 
    // Shuffle data before each pass
    shuffle: true, 
});

 

With the additional parameters, we can tweak the number of images processed before the internal model parameters are updated (batchSize), the number of training iterations using our dataset (or epochs) and request that the data is shuffled again before each pass through via the shuffle option.

 

Transfer Learning

 

If you have gotten to this point in this extensive piece, you will realise how involved it can be to create your own CNN model for image classification. If we want to leverage an existing model, and all of the knowledge it has, we can use a technique called Transfer Learning. As illustrated in the below diagram, Transfer Learning is where we create a new classification head for our precise task that uses the features generated from another model:

Transfer Learning Example | Source: What is Transfer Learning?

MobileNet can be retrained for your own use case via transfer learning if the out-of-the-box classifications don’t suit your needs. However, unlike the model we have loaded directly from @tensorflow-models/mobilenet, you need the feature-vector version that generates the features via the model’s convolution and pooling stages.

 

This model can be loaded from TFHub using the tf.loadGraphModel utility as shown in the below:

 

const tf = require("@tensorflow/tfjs-node");

async function getMobileNetFeatureModel() {
  const URL =
    "https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/default/1";

  const mobileNetModel = await tf.loadGraphModel(URL, { fromTFHub: true });

  // Warm up the model
  tf.tidy(() =&gt; {
    // 3 for RGB images
    mobileNetModel.predict(tf.zeros([1, IMAGE_HEIGHT, IMAGE_WIDTH, 3]));
  });

  return mobileNetModel;
}

 

One additional step I have done here is to warm up the model by passing zeros through the model first. This is an optional step, but it does speed up the processing of the initial image. So I would probably use this technique in future with the other approaches covered in this piece.

 

Next, we need to create the image classification head to use alongside the MobileNet model:

 

function getTransferClassificationModel() {
  // Alternative model classification head
  const myTransferMobileNetModel = tf.sequential();
  myTransferMobileNetModel.add(
    tf.layers.dense({ inputShape: [1024], units: 128, activation: "relu" })
  );
  myTransferMobileNetModel.add(
    tf.layers.dense({ units: CLASS_NAMES.length, activation: "softmax" })
  );

  myTransferMobileNetModel.summary();

  // Compile the model with the defined optimizer and specify a loss function to use.
  myTransferMobileNetModel.compile({
    // Adam changes the learning rate over time which is useful.
    optimizer: "adam",
    // Use the correct loss function. If 2 classes of data, must use binaryCrossentropy.
    // Else categoricalCrossentropy is used if more than 2 classes.
    loss:
      CLASS_NAMES.length === 2
        ? "binaryCrossentropy"
        : "categoricalCrossentropy",
    metrics: ["accuracy"],
  });

  return myTransferMobileNetModel;
}

 

Notice we are creating similar dense layers for the classification layer that we did in our custom model. We’re also using the same optimizer and loss functions.

 

Next, we need to train this model. Using the same logic as prior examples to get a set of image tensors and labels, we extract the features and fit the model using the below code:

 

  // Tensor and label generation logic omitted

  // Initialize both models (as per above)
  const mobileNetModel = await getMobileNetFeatureModel();
  const myTransferMobileNetModel = getTransferClassificationModel();

  // Get features from MobileNet
  const mobileNetFeatures = images.map((image) =&gt; {
    // Normalize the image data. Image data is always in the range of 0 to 255, 
    // so you can simply divide resizedTensorFrame by 255 to ensure all values are 
    // between 0 and 1 instead as MobileNet expects
    const normalizedImageTensor = image.div(255);
    return mobileNetModel.predict(normalizedImageTensor.expandDims()).squeeze();
  });

  // Train the new model using MobileNet features similar to other examples
  tf.util.shuffleCombo(mobileNetFeatures, labels);
  const singleImageTensor = tf.stack(mobileNetFeatures);
  const labelsTensor = tf.tensor2d(labels);

  await myTransferMobileNetModel.fit(singleImageTensor, labelsTensor, {
    // Number of samples to work through before updating the internal model parameters
    batchSize: 5, 
    // Number of passes through the dataset
    epochs: 10, 
    // Shuffle data before each pass
    shuffle: true 
  });

 

Once the model has been fitted, the same approach is used to generate the features to pass into model.predict:

 

async function classifyAllImages(mobileNetModel, model) {
  const imagesResponse = await getAllImages();
  const images = imagesResponse.hits.hits.flatMap((result) =&gt; {
    return { id: result._id, url: result._source.image_url };
  });

  for (image of images) {
    const tensor = await getResizedImageTensor(image.url);
    const normalizedImageTensor = tensor.div(255);
    
    const features = mobileNetModel.predict(normalizedImageTensor.expandDims()).squeeze();
    const results = await model.predict(features.expandDims()).squeeze().data();

    const predictions = Array.from(results)
      .map(function (p, i) {
        return {
          probability: p,
          className: CLASS_NAMES[i],
        };
      })
      .sort(function (a, b) {
        return b.probability - a.probability;
      })
      .slice(0, 2);

    // Elasticsearch utility to update the document with the additional transfer classifications
    updateDocumentWithTransferClassification(
      image.id,
      predictions[0].className,
      predictions
    );
  }
}

 

For both the custom model and the transfer classifications, the Elasticsearch documents in the existing documents are updated using the update operation as they were previously created. The logic for the transfer classification approach is presented below:

 

async function updateDocumentWithTransferClassification(documentId, category, predictions) {
  const myModelClassifier = { 
    category:  category,
    predictions: predictions
  };
  try {
    await esClient.update(
      {
        index: index,
        id: documentId,
        script: {
          lang: 'painless',
          source: `ctx._source.my_transfer_model_classifier = params.classification`,
          params: { classification: myModelClassifier }
        }
      }
    );
  } catch(e) {
    console.log(e);
  }
}

 

Note that to update the custom model classifications, the script.source attribute should be changed to ctx._source.my_model_classifier.

 

Key Results

 

Analysing the results of both the model classifications and the players of the web game was very easy. By enriching the user-classifications index with an index pipeline I was able to have all classifications in a single object to compare:

 

PUT _ingest/pipeline/add-classifications-to-gameplay
{
  "processors": [
      {
        "enrich": {
          "description": "Add model classifications based on image URL for final results",
          "policy_name": "add-classifications",
          "field": "image_url",
          "target_field": "models",
          "max_matches": "1"
        }
      }
    ]
}

 

The add classifications enrichment policy adds the prediction results from each model to the gameplay result:

 

PUT /_enrich/policy/add-classifications
{
  "match": {
    "indices": "classifications",
    "match_field": "image_url",
    "enrich_fields": [ "coco_ssd_predictions", "mobilenet_classifier", "my_model_classifier", "my_transfer_model_classifier"]
  }
}

//  Create a streamlined system index called the enrich index, which is used to enrich incoming documents
PUT /_enrich/policy/add-classifications/_execute

 

By enriching the results for the image against the gameplay object, it’s easy to pull back the final comparisons at the end of the game for the game scoreboard with a simple match query, as present in elasticsearch-util.js to produce the following leaderboard:

Then to track multiple games, we can use a handy Kibana dashboard, just as I have below:

Looking at the performance of myself and my family across 3 games each, we are very good at finding the cake, finding that we correctly classified 90 distinct images 86% of the time. This is far better than my own model which thought all images were cake:

Using transfer learning improved the situation and found that 319 of the images were cake:

Meanwhile, of the pre-trained models, COCO-SSD outperformed MobileNet by identifying a higher proportion of cake.

While I understand MobileNet’s assertion that many cakes look like candles, you don’t want to mix up delicious cakes with non-edible candles!

Conclusion

In this piece I’ve walked through my journey of learning image classification in JavaScript using TensorFlow.js using images extracted using Playwright and the Unsplash API via the unsplash-js wrapper into Elasticsearch. This experience has given me an appreciation of the complexity of building machine learning models that makes me thankful for those building the models I use in my pet projects, including for vector search. I still have a lot to learn since I’ve found my manual classifications of cake are more accurate than existing models as well as my custom model and transfer classification.

Do check out all of the code for each approach in this GitHub repo. If you want to pit your own cake-finding skills against these models, play the game at https://is-it-fake.netlify.app/

Thanks for reading!

Electric Youth

Why LLMs are Like My 4-Year-Old

One of the biggest buzzwords of 2023 was AI, particularly Large Language Models, or LLMs. If you missed the hype (really?!), an LLM is an AI algorithm trained on large volumes of data that can understand and generate written content in the language on which it was trained. Since Chat-GPT emerged at the start of 2023 we’ve been using it to summarize and generate text and code to solve our everyday problems.

 

Child holding hands with a robot

 

We’ve watched with awe at some of the amazing benefits that have appeared to help us with our work productivity in the case of UK civil servants, or to help us discuss life’s difficulties with Psychologist or to chat to our favourite characters like Super Mario in the case of Character.ai chatbots. Furthermore, we’ve also been horrified at the potential for them to spread harm through disinformation, or be used to create tools for criminal purposes. Even the use of articles to train these models is under scrutiny for potential violations of copyright with open cases lodged by The New York Times and authors John Grisham and George RR Martin.

 

My son pre-dates LLMs, having burst onto the scene just over 4 years ago. Like any 4 year old he comes up with intriguing ideas that he spouts with more confidence than I could ever imagine to have. Yet my geeky husband and I couldn’t help but notice some rather common traits between him and LLMs. In this piece, I’ll share some of these commonalities in a slightly more humorous take on LLM usage and development concepts.

 

Raise the Knowledge

 

The concepts of grounded knowledge and the application of this knowledge are similar between young children and LLMs. Both rely on observed sources of information when generating responses to the questions we ask.

 

Prominent psychologist Jean Piaget in his theory of cognitive development outlined the 4 key stages of cognitive development that children progress through. Through these stages, children are building their mental model of the world by building associations between objects they encounter and operations associated with them. For example, infants in the Sensorimotor Stage learn about object manipulation and object permanence through their sensory experiences. These interactions can be limited by the objects they are given to interact with, including scenarios of gender norms of providing girls and boys with different toys.

 

As children age they can also form incorrect assumptions, such as young family members who assumed women only drove cars because they were used to being driven around by Mum and Gran. Or connect unrelated concepts:

 

Octopus speaks Spanish Mummy. Bonjour!

Mini R, aged 4

 

LLMs can similarly be influenced, they are generating an answer to your question using the patterns they have picked up in their training. One of the reasons the aforementioned copyright cases are popping up like the game whack-a-mole is due to the sheer volume of data sources used to train them. They are easy to mislead with poisoned data. This is already possible for generative image models using tools like Nightshade, and many are confident textual models can be manipulated with providing poisoned documents for training.

 

 

Handling specific use cases or working with proprietary data the LLM is not trained on requires grounding with accurate sources. As shown in the above diagram from Google’s grounding blog, semantic search capabilities using vector search technologist allow LLMs to use specific data to apply sensible rules and sources for the generated responses.

 

Sponge

 

Children are sponges. You never know what words or phrases they will pick up as they are always listening. The panic parents feel when their child unintentionally picks up swear words, or in my case, the word ridiculous, and recites them is real. For a while afterwards, the word will pop up in unexpected contexts as children try to figure out where in their internal schema this term should fit.

 

Returning to Piaget’s theory of cognitive development, my 4-year-old son is currently in the Preoperational Stage. At the start of this phase children are strongly influenced by how things appear, or the things they hear, and assume other people see the world the same way as they do. How they perceive the world is strongly informed by the objects they encounter, and the language used by others around them, meaning they mimic what others say without knowledge of wider context. Or sometimes apply unexpected actions to objects.

 

In the heart of Pando

Mini R, aged 4

 

This pattern is something that LLMs can also inadvertently do based on training data. They may generate incorrect answers by forming false connections between unrelated sources. A prominent example of this comes from Google Bard’s first demo in early 2023 where it incorrectly stated the James Webb Telescope took the first picture of a planet outside our solar system, rather than the correct answer which is the Hubble Telescope.

 

Grounding can partially address the issue of source confusion. But for the usage of terms in nonsensical contexts, development of domain-specific LLMs such as BioBERT for the biomedical field and BloombergGPT for finance are under development. These are intended to restrict the generated responses to utilize and hopefully reduce some of the unexpected results that can be generated by general-purpose LLMs.

 

Don’t Stop Believin’

 

The first time I used ChatGPT I found the tone of the generated answers interesting. Unlike myself and many others suffering from the confidence chasm triggered by impostor syndrome, it conveys a tone of confidence even when the answer is incorrect.

 

LLMs don’t think. They generate responses based on the language patterns they have picked up through training. Therefore they are not able to determine like humans if they should give you the information you have asked for. Instead, applications need to intercept and potentially refuse to answer these toxic questions. For example, do you really want to tell someone how to make a deadly chemical?

 

Early versions of ChatGPT suffered from issues of generating false sources rather than stating their source, such as the 2023 case in the US where lawyers were fined for submitting fake citations generated by ChatGPT. This generation of false information is known as hallucination.

 

Of course, the wee man thinks! That is one key difference. But he does tell a good tale and can struggle to convey the date a particular event happened or be blindly convinced that something is true.

 

The Tangent

 

My son gets very easily distracted. As do many young children. The TV coming on can stop him telling the most engaging of tales mid-way, or leave me asking several times what he wants to eat. Asking him a question while speaking can trigger a whole new story altogether:

 

I couldn’t go to the toilet Mummy. I got distracted by the ball!

Mini R, aged 4

 

Just like any software system, LLMs can be hacked in various ways. This is exactly why OWASP released a dedicated Top 10 for applications using LLMs. There are various ways to hack an LLM as covered in this Infosecurity Europe piece. One particular vulnerability, known as Prompt Injection involves crafting prompts to encourage the model to leak data or perform other unintended actions. Just like that ball that interrupted the wee man’s trip to the loo by encouraging him to chase the ball.

 

Edge of Evolution

 

Young children are sponges. The rate at which they learn and retain information is absolutely astounding. I had certainly forgotten the amount of information I retained throughout my school years. Since my son started school I’ve been amazed at how quickly he has been learning to read and remember sounds.

 

Today we learned OO, Mum. Zoom to the moon!

Mini Richmond, aged 4

 

New LLMs are released all the time and are becoming more sophisticated. Since 2021 there has been an explosion of models being built and released, as shown in the generated diagram from Mooler’s LLMs Practical Guide.

 

 

The evolution of these models also means that we are seeing metrics used to evaluate them varying significantly, as highlighted in the comparison table from a 2023 research paper:

 

 

The size of training datasets has increased. The number of parameters available for tuning the model is increasing with newer models. Furthermore, the number of tokens processed is also increasing. It’s easy to assume that parameter and token counts point to better models, but the reality is that comparing these models to determine suitability for your use case is becoming more nuanced.

 

We in turn learn from LLMs too. Just as I’m learning phonics over the word memorization techniques I used at school thanks to the wee one, we ask LLMs to answer our questions. However, in both situations, we need to ensure we can cross-check the information and source legitimacy to prevent the spread of disinformation.

 

Change is Now

 

Here I’ve covered the similarities between my 4-year-old and LLMs. Just like in 2023, I’m expecting AI to continue to dominate our news just like it did in 2023.

 

Happy family chilling on bed

 

One of the things I was told by everyone before my special little guy was born was how much having a child changes your life. Any parent will tell you that it completely changes your world, perspective and priorities. AI generally, and LLMs specifically, have already changed how we generate and consume information.

 

We’re using ChatGPT for many different things, from summarizing text to generating responses to emails. Just as my growing child will change and impact my life and work, so will AI in the coming years.

 

Thanks for reading!

Rip It Up

Starting Over With Serverless Functions

This week I’ve had the fun and frustration of building my first app in a while. Life as a developer advocate has periods of busy social energy around conferences as well as quiet focus to work on content. Prior roles I’ve had before had the majority of one or the other, referring specifically to the manic calendar of being a team lead and engineering manager compared to the quiet focus required for developers.

 

So why fun? This week I’ve had time to build an app and revisit my youth by rebuilding my master’s thesis game Fu-Finder. Getting in the zone and tinkering with a coding project scratches the engineer itch I often get when I’ve not written any code in a while. So the euphoria of getting something working has been great. Kind of like the joy of winning with my favourite character in the Street Fighter games as a kid.

 

But it’s also been frustrating! I’ve had to make a few big design changes along the way. I ripped out a library I was using for building the search experience after finding the documentation difficult to navigate and that I spent more time getting their components to do what I wanted than just writing my own. I ripped out my server implementation as well when I started to think about hosting. My background in banking means thinking logic resides in a continually running server, which doesn’t really work when I have to consider utilization and cost. I also ripped out my monorepo manager when realising my serverless functions don’t need to reside in a dedicated server app, and that running them locally was just not happening. Error after error left me feeling rather Blanka-esque (cheers for the inspiration Keith!)

 

 

Here I walk through using serverless functions, specifically using Netlify, alongside Elasticsearch JavaScript Client and React, to show how I’ve simplified a complex monorepo implementation into a far simpler project.

 

What the serverl*ss?

 

Serverless has been a long-standing buzzword that I’ve always found slightly misleading. Traditionally, web developers deploy a running process on server hardware somewhere that will remain alive and respond to calls made from another component, most notably a frontend component as in this case.

 

Serverless functions do not mean that the box is gone, but that it’s abstracted away by a cloud provider. This can make it easier for new developers to get started, but for more experienced engineers like myself, it requires unlearning the server habit.

 

A serverless function is an ephemeral process that spins up temporarily to perform our logic before standing down. It’s also stateless, meaning that the data doesn’t persist and we as developers need to ensure our data is stored elsewhere such as a database, Elasticsearch cluster, Kafka broker or queue.

 

Prerequisites

 

All of the code discussed in this post is available here on GitHub. Additionally, you will need to have the following elements installed:

 

  1. NPM package manager for installation and package management.
  2. Netlify CLI for local running of serverless functions.

 

It’s worth noting there are loads of different tutorials online for writing Netlify functions. I took inspiration from two articles from CSS Tricks and Netlify.

 

Configuration

 

Serverless providers, including Netlify which I am using here, require configuration to pick up your functions. Here we specify a netlify.toml file to explain how the site is built, and deployed (if you’re not making use of the GitHub connection and configuration via the UI which I did).

 

There are many options covered in the documentation that you can specify. I found I needed to specify build options to have my React app running locally alongside the functions.

 

[build]
command = "npm run build" # React app build command
functions = "src/functions/" # functions location
publish = "build" # static content path

 

A common option that I didn’t use is redirects, which allows you to specify redirection logic. This is particularly useful in the Netlify case where the path by default resolves to .netlify/functions/<my-url-path>. When building an enterprise application, or one for something other than a pet project, you probably don’t want to expose the provider. One cool thing you can do is stitch old and new together using the :splat operator:

 

[[redirects]]
  from = ".netlify/functions/*"
  to = "/api/:splat"
  status = 200
  force = true

 

The above configuration would mean automatic redirection from a default path such as .netlify/functions/document to api/document. It’s not something I explicitly needed for a prototype, but I’ve included it here as I expect to use it for future projects.

 

Function Writing

 

Initially, I took the approach of wrapping my Express server in a single function using the serverless-http module, meaning that my paths would be one level below. So for example, my /document endpoint to get an individual document from Elasticsearch by ID sat alongside was present in the functions/api.ts file, resulting in the function api/document. Conceptually I found this difficult to rationalise in my head as I was making changes.

 

API endpoint design best practices recommend making URLs easier to read and making use of nouns where you can. Adhering to this means avoiding deep paths and using separate handlers. Below is the document function used in my game through POST .netlify/functions/document.

 

// Note: Netlify deploys this function at the endpoint /.netlify/functions/document
export async function handler(event, context) {
  const request = convertRequest(event.body);

  if (!request.documentID) { 
    return generateResponse(500, 'Document ID not specified');
  }

  try {
    const results = await getDocumentByID(request.documentID);
    
    return generateResponse(200, results);
  }
  catch(e) {
    console.log(e);
    
    return generateResponse(500, e);
  }

 

Awaiting Workloads

 

The stateless nature of these functions means that data must be persisted somewhere and accessed from a store. Here I have made use of a utility using the Elasticsearch JavaScript Client to perform the required searches. The example below makes use of an IDs query to return an individual document.

 

import { Client } from "@elastic/elasticsearch";

const client = new Client({
    cloud: { id: cloudID },
    auth: { apiKey: apiKey },
});

export function getDocumentByID(documentID: string): Promise<any> {
    return client.search({
        index: index,
        query: {
          ids: {
            values: documentID,
          },
        },
    });
}

 

Unlike traditional server implementations where to paraphrase Beyoncé, you shoulda put a spinner on it to communicate a long-running delay we consider necessary, we need to be mindful of the return time from data services. Here I’m making use of the free functions from Netlify, which have memory and usage limits depending on your plan. Limit responses to essential fields and documents to ensure response within limits, as well as to avoid the dreaded Elasticsearch circuit-breaker errors.

 

Request and Response Handling

 

The generateResponse function is a helper used to generate the response in the expected format. It’s important to use HTTP error codes to denote success and failure and allow for error detection and handling on the UI, which is why success is denoted by 200: OK compared to error 500: Internal Server Error. The generateResponse method ensures the response content is stringified for return to the UI, along with the status code in the expected int format:

 

export function generateResponse(statusCode: number, data: any) {
    return {
      statusCode: statusCode,
      body: JSON.stringify(data)
    };
  };

 

It’s worth noting that the response also needs to be parsed into valid JSON using the JSON.parse JavaScript method, which I’ve extracted to another utility method convertRequest:

 

export function convertRequest(data: any) {
    return JSON.parse(data);
}

 

Running Locally and Deploying

 

One of the reasons I’ve avoided serverless functions for so long was the ambiguity of how to run and validate locally. As an advocate running demos locally is a useful backup for unreliable internet, and as a frontend engineer in banking running the app locally was imperative for debugging and E2E test development. Pushing changes and finding issues when deploying to Netlify is not ideal.

 

Let’s recall our netlify.toml, and the command configuration:

 

[build]
command = "npm run build" # React app build command
functions = "src/functions/" # functions location
publish = "build" # static content path

 

Kicking off the Netlify CLI using netlify dev will spin up not just my React frontend as I have the command configured, but also each of my serverless functions. Huzzah!

 

Deployment is pretty easy given the GitHub integration that Netlify has, especially when our netlify.toml already has the build command and publish options configured. I’d recommend following the guide in their blog.

 

Conclusions

 

Despite ripping out my Nx monorepo and replacing the Express app with functions being a frustrating and confusing ride this week, I’m glad I did it. One of the best things about my job as an advocate is that I am already learning new things and building my skills. My experience in banking tech was that building financial software doesn’t always grant you the luxury of playing with shiny new tech toys.

 

All my fellow software engineers will attest to the satisfaction of getting something working and deployed. But there’s one other fantastic yet underrated feeling: when you get to delete redundant code. With 31,672 additions and 25,091 deletions I’m satisfied that I have a better-structured project that will be far easier for others to understand.

 

Happy serverless coding!

Charge Me Up

Respecting the Social Battery in DevRel

Over the past year, I’ve gained a great insight into the developer and community focus of developer relations. As an advocate and engineer, I’ve enjoyed connecting with and learning from so many wonderful and intelligent people.

 

As an extrovert with introverted tendencies, I’ve often found some of these events to be as draining as they are engaging. And at my first Engineering All Hands this year I found I’m not the only one. We had a great conversation on tiredness, with one colleague referring to their depleted social battery. I had never heard of this term, but it resonated strongly with how I was also feeling by the end of the week.

 

Phone with empty battery

Ever feel like you’re running on empty?

 

In this piece, I discuss the factors that impact our social battery generally, as well as those specific to DevRel and tech. I’ll also share tips on managing your own social battery, learned from my wonderful colleagues, and resources you can use to manage your own social battery and well-being.

 

Like a Battery

 

The social battery is the allowance of energy a given person has for socialising before it starts to harm their well-being. Introversion and extroversion is a scale, which we can move up and down throughout our lives. Having been a prominent extrovert for a large portion of my life, and therefore being energised by social interactions, I’ve had points of introversion as well. Everyone has a different capacity for social engagement, or battery size, and this battery size and capacity ebbs and flows.

 

The metaphor of a battery representing social energy charge always reminds me of the Duracell Bunny. As a child, I would regularly see TV adverts of bunnies powered by competitor batteries quickly becoming tired, whereas Duracell would keep going for longer.

 

Duracell Bunny

We can’t all just keep going like the Duracell Bunny!

 

But it’s not just tiredness that is a sign of a depleting social battery. There are other signs, including:

 

  1. Mental exhaustion or difficulty processing new information.
  2. Periods of quiet or inactivity in group conversations.
  3. Irritation caused by not only others but loud noises, music or lighting.
  4. Difficulty responding to emotions or verbal cues from others.
  5. Physical symptoms such as headaches or back pain.
  6. Insomnia or difficulty falling asleep due to overstimulation.

 

Any of these side effects can also have an impact on productivity. As can the working environment, which I’ve written about before based on my experiences of working in a busy and overcrowded office. We need to be mindful of the causes, and on the lookout for the symptoms in ourselves and each other.

 

Human Battery

 

Tech does have some industry-specific challenges in supporting the social battery of those working within it. We’re not talking about the developer stereotype of an introverted developer hiding in the corner of the office in front of their laptop coding away in a set of enormous noise-cancelling headphones. The explosion of increased collaboration driven through the adoption of agile, or sadly fr-agile, ways of working and techniques such as pair programming means that everyone working in tech is working in social ways with less time for isolated work. I must emphasize that these techniques are wonderful and essential for building better software that solves real-world problems. But if they are not used in a balanced way they can drain people anywhere on the introvert-extrovert scale.

 

Hands with Heart Paint

DevRel and community can introduce challenges in maintaining a fully-charged social battery

 

It may seem like DevRel is an extrovert-only club, but I’ve found having a mixture of individuals on the energy scale helps accommodate developers across the community. In the DevRel world there are several unique considerations:

 

  • Advocates, program managers and company representatives moving between extremes of solitary work building content and highly social settings such as meetup talks and conference booth duty.
  • Interacting with a mixture of introverts and extroverts within the community.
  • The increasingly remote nature of our work as we complete tasks working at home, or on public transport as we travel to events. Working for a company such as Elastic that is distributed by design means many individuals will visit offices occasionally, myself included.
  • Traveling long distances for a conference or event can mean working while managing jet lag, which can be a draining experience.

 

What’s more important is that we acknowledge industry and environment-specific factors, and give space and empathy to help each other prevent or manage a drained social battery. This includes colleagues, counterparts and the developers and users with which we engage.

 

Low Battery

 

Irrespective of where you feel you sit on the introvert/ extrovert scale, it’s important to build a personal toolkit to prevent or manage depleted social energy levels. Here are some tips that have worked for me, as well as some I’ve learned from others:

 

  1. Be sure to take the idle time that you need to do things you enjoy when you need. Perhaps it’s listening to music or a podcast, as it is for me. Or maybe you are more of a knitting person. Brief regular breaks help you maintain charge.
  2. Balance short and long spells to maintain energy. This has been the biggest challenge for me while juggling work and parenthood, even with a supportive co-parent on my side. Taking longer spells for restorative activities, which for me are things like reading a book in the bath or taking a walk outside with my camera, is necessary to maintain energy.
  3. Use conference schedules or your personal meeting calendar to plan potential points for personal time. It can be useful to take a planned break on particularly busy days to recharge your energy before it is completely exhausted. Even if it’s 10 minutes to grab a cup of tea as I do before giving a conference talk.
  4. Identify the social events you can step away from to avoid order-stretching yourself. Sometimes at work gatherings or tech conferences, you may feel you have to attend every social. But the reality is social engagements will be optional.
  5. Take time to relax at home with family or on your own after a long trip. Chilling by yourself in your hotel on a work trip can help with a temporary restoration, but home is where the heart is after all!
  6. Support others when they step away, and respect their decision to take time for themselves. If you are a natural extravert this may be challenging as it’s at odds with how you get your energy. But it’s the best way to garner mutual respect when you need your own break.
  7. Be friendly and open to those who approach the stand. If someone has low energy they may want to just have a look at the swag or any product information, rather than have an in-depth conversation. Don’t force the issue.
  8. Seek out nature or fresh air. Be it a hike or even a step outside, both a great ways to get energy back. Especially if you’ve been sitting inside an office or conference venue all day.
  9. Use the Pac-Man Rule to allow people to join conversations if they wish. This is particularly inviting for those who don’t know many people at an event.
  10. Withdraw from events if it’s getting too much. Self-care comes first!

 

All Together Now

 

I still consider myself an extroverted introvert. It has taken me quite a while to be comfortable saying no to social events and taking my recharge time. Especially as a parent caring for an excitable and enthusiastic little boy who can definitely deplete your energy quickly! It’s important to take the time to find your social limits and the activities that help you recharge those batteries!

 

In researching this piece I found these resources helpful:

 

 

Do check them out. Best of luck maintaining your DevRel social battery!

 

Thanks for reading! Do share if you have additional tips to share on managing your social battery charge.

Take a Picture

Programmatic Screenshot Capture Using Playwright and Node.js

As engineers, we are always looking for shiny new greenfield projects or rewriting ageing legacy applications. We rarely get the opportunity to rebuild an application from the days we learned to code and see how far we have come as a developer. I’m lucky enough to be in that same situation.

 

Moving back into the search domain through my role as a Developer Advocate at Elastic has inspired me to revisit the Fu-Finder game that I built for my master’s thesis. One of the first tasks required to build this game is revisiting the URL dataset of the old game, and capturing screenshots to show in the game. A large number of the URLs have changed or no longer exist. But for those that do I need updated screenshots for players to search for.

 

Previously I used WebKit and Python when building the original game. The majority of e2e test and automation frameworks have screenshot capabilities, including Cypress and Selenium. But since I’ve been playing with Playwright and @elastic/synthetics, I’ll show how Playwright and JavaScript can be used to capture these screenshots.

 

Pictures of You

 

The final version of the script get-screenshot-images.js is available on repo carlyrichmond/elastic-fu-finder. The process for generating the screenshots involved 3 key steps:

 

  1. Extract the URLs I want to capture. Following an experiment using the Elastic WebCrawler, I have a set of URLs present in the index search-elastic-fu-finder-pages that I can pull out using a search call to return all results.
  2. Set up the Playwright browser configuration.
  3. Capture a screenshot for each URL and save.

 

There are many great resources out there that show how to capture screenshots using any of the myriad of automation frameworks. I came across this amazing article by Chris Roebuck that covers 7 different approaches. I used the Playwright example as a basis, ending up with code that looked a little bit like this:

 

const { chromium } = require('playwright');
const imageFolder = 'images/screenshots';

// Elasticsearch URL extraction executed before getScreenshotsFromHits

// param: hits, results consisting of document id (_id) 
// and document source (_source) containing url
  async function getScreenshotsFromHits(hits) {
    let browser = await chromium.launch();
    let page = await browser.newPage();
    await page.viewportSize({ width: 3840, height: 1080 });

    for (const hit of hits ) {
      const id = hit._id;
      const url = hit._source.url;

      console.log(`Obtaining screenshot for ${url}`);
      
      try {
        await page.goto(url);
        await page.screenshot({ path: `${imageFolder}/${id}.png`}); 
      }
      catch(e) {
        console.log(`Timeout received for ${url}`);
        continue;
      }
    }

    await browser.close();
  }

 

Playwright gives us access to various different browsers. However, I found a rather troubling issue when using Chromium against a subset of my websites.

 

Don’t Stand So Close to Me

 

Some websites blocked my script, which resulted in Playwright capturing a screenshot for a 403 error in the browser, exactly like the one below.

This was a new issue that I didn’t encounter previously when using WebKit way back in the day. It’s not surprising given the expansion of the web over the past decade that websites are protecting themselves from automated agents. Especially if they expose a public API where the data can be extracted in a controlled way.

 

A bit of Googling led me to good old Stack Overflow, and this thread on Python access with Chromium. This old yet detailed post mentions detection of the User Agent to block traffic, which makes sense.

 

Local Boy in the Photograph

 

I could have simply excluded the impacted URLs from my dataset. I also considered using the new Headless Chromium option based on this other Stack Overflow post to address the limitation.

 

In the end, I decided to use an alternative browser. I also played around with the fullPage option, which was a tad too large, and the clip settings to get the content that I wanted from my pages:

 

const { firefox } = require('playwright');
const imageFolder = 'images/screenshots';

// Elasticsearch URL extraction executed before getScreenshotsFromHits

// param: hits, results consisting of document id (_id) 
// and document source (_source) containing url
  async function getScreenshotsFromHits(hits) {
    let browser = await firefox.launch();
    let page = await browser.newPage();
    await page.viewportSize({ width: 3840, height: 1080 });

    for (const hit of hits ) {
      const id = hit._id;
      const url = hit._source.url;

      console.log(`Obtaining screenshot for ${url}`);
      
      try {
        await page.goto(url);
        await page.screenshot({ path: `${imageFolder}/${id}.png`, fullPage: true, 
clip: { x: 0, y: 0, width: 3840, height: 1080 }}); 
      }
      catch(e) {
        console.log(`Timeout received for ${url}`);
        continue;
      }
    }

    await browser.close();
  }

 

With this trusty code, we’re now able to extract screenshots successfully. Woohoo!

Conclusions

 

I’m excited to say the Fu-Finder sequel is in progress thanks to Playwright helping me extract screenshots from a set of pages. I have limited execution of this script to a one off extraction to respect these sites. The last thing I want to do is initiate a denial of service against them!

 

When crawling to extract the content, such as with a crawler, I would respect the restrictions put in place by a site’s robots.txt as I did with my original list of URLs. The majority of Open Source and Commercial Crawlers will respect this file, and so should you!

 

Happy screenshot capture!

(Not So) Basic Instinct

Nurturing Problem Solving Instincts in the Tech Industry

Nature versus nurture is an ongoing debate as to whether human behaviours are driven by inbuilt natural factors already there, or are formed through environmental factors such as parenting and life experience. When considering the skills required for building software, or indeed anything else we do in life, you always wonder if it’s always been there or built via experience.

 

Other life events and experiences make us better technologists, including parenthood, caring, traveling, and being just a friendly human. I always remember chatting about my upcoming parental responsibilities with a friend. You’re never sure if you’ll be a good parent or not, and feel the weight of responsibility in looking for a tiny helpless human. My friend reassured me that the hidden kernel subroutine will kick in when you’re ready, which I found amusing and reassuring. Thinking about that story now and how my now 3 year old has turned out (shock!) leads me to realise that some instincts were there, but a lot of the instincts formed through practical experiences such as trying to get them the baba to sleep at 3am, or learning tricks from my husband how to get a slippery toddler out the bath (true story).

 

Mum cuddling swaddled baby

 

Becoming a good software engineer, and Mum, is hard and requires you to build your own instincts

 

Over my 11 year career in tech, I’ve noticed with each move I become more comfortable with uncertainty, and find my feet more quickly than with the last move. It is my opinion that through my school, university and software engineer career I have built instincts through trying, failing, adapting and learning from others. Here I reflect on the main types of instincts I’ve nurtured through my technical career, and share tips on how you can build these instincts too.

 

Helps Me Help You

 

You may not know this, but my first role straight off my 15 week training program within the bank was a rather mixed role. I was a developer reading rather than writing Perl and coding in Python, SQL and AxiomSL (aka a data management platform with an in-built ETL used for financial domains such as regulatory reporting, capital reporting and liquidity management calculations which now looks to be part of the company Adenza…). However, I also supported the calculation and submission efforts by users in production. Normally, as I came to find later, these roles are not normally combined.

 

This dual responsibility definitely made me better at multitasking, or at least I think it did. I know from psychology But it also introduced me early to the need to prioritise my work. This was a slightly different experience to my peers who didn’t have the same support commitments when starting out. If it got to them as an urgent escalation, it was a drop-everything situation. Yet for me it was more nuanced. Submission issues were a red alert situation, absolutely! However, some user production questions were a mere DEFCON 5 situation, or for those who haven’t learned the lingo from Mr R’s love of Star Trek, not a big deal at all.

 

Ambulance With Flashing Blue Lights

 

My first role helped me learn the importance of triage and that the nosiest issues is not always the most important

 

The context was important in determining the priority. This taught me early the importance of asking questions. Just like an hospital emergency room scenario Darria Long discusses in her TED talk, the loudest patient is not always the highest priortity. Issue triage typically involved me asking questions to categorise an incident such as:

 

  1. What environment is this issue in? Production may be critical depending on impact, but QA may not be depending on whether they are using it for upstream application verification compared to testing adjustments before applying them in production.
  2. How do you expect this logic or feature to work? Differing expectation versus reality is still something I see even today as a Developer Advocate.
  3. Do you have any screenshots or error messages? This question still proved useful later when I transitioned into web frontend development.
  4. What is the impact of this issue? Knowing if this impacts an external submission today versus internal reporting was a key indicator of priority for me at that time.

 

When it came to requirements prioritisation this was my first insight into the subjective nature of importance. Sadly I got stung a couple of times when focusing on building something when they wanted me to focus on another requirement resulted in some uncomfortable questions. When you first start as an engineer, you want to please users and establish a reputation for delivery.

 

Every issue is important to someone. Therefore, depending on who you speak to it’s easy to be led astray and focus on building the thing to solve the problem, especially if it’s easy and you’ve built confidence in the technology you need to use. It highlights the importance of building in small increments as advocated by agile principles and agreeing on a common strategy as a team, rather than working in waterfall as independent units, and not discussing priority enough.

 

An Honest Mistake

 

Instincts on the root cause of errors is another skill that requires nurturing to master. When I moved to be a frontend web developer, I learned the importance of reading and interpreting error messages and logs. I indeed had to read logs and interpret error messages when things went wrong. However, what made this different is that this was my first tech stack move. At this time I was learning Angular, Typescript and many other different technologies.

 

Anyone who’s done any web development in the last 10+ years will be aware of the framework and tooling explosion in that space. It can be intimidating to pick them up as they often have their own opinionated patterns you need to follow. Angular in particular enforces very strong structure and style if you check out the style guide. In addition to learning new terms and patterns, you also need to develop instincts for reading and processing stack traces emitted when things go wrong. While advancements in recent releases have improved the developer experience, such as the improved developer experience for the banana in the box error introduced in Angular 14 in 2021, the reality is that diagnosing error messages is an art that we hone instincts for with each feature we build, and through researching and understanding the intricacies of how they work under the hood.

 

404 Error with Upside Down Smiley Face

 

If only all error traces we counter in web development were as straightforward as 404!

 

We also get better and researching issues and building search-fu to understand the relevancy of information we find. When you start as an engineer, you may be more likely to reach out to a mentor to help with confusing error messages first. However, later as you get better at using Google, or your favourite alternative search engine, you get better at finding not the exact error message, but find related messages triggered from other libraries and from there and generate ideas on how to solve the problem at hand. These skills have proven not only useful in my role as a developer. As an advocate who looks to build content and show via prototypes the features of particular technologies, diagnosing and fixing error messages, possibly in unfamiliar ecosystems, has helped me learn Elasticsearch and the technologies I advocate for quickly, and continue to keep up to date with them.

 

Human After All

 

A common career path within technology, but not the only path, to engineering management also requires learning. While often this progression is suggested as the default path, it is a role I believe requires building specialised skills that also need to be grown. Just as I did as an engineer, as a manager I engaged in research, training and reading to build the skills required of a good manager and technical leader. Let’s not confuse leadership and management. They are not the same thing.

 

Stepping into management can initially be a fearful construct. Breaking people seems far easier and scarier than breaking software. For me, I found the need to build my empathy, delegation and teaching skills to be a better people manager. There is also the need to get up to speed with company policies, such as sickness, performance and parental policies, and resources for career growth and mental health. As a manager, you need to support people through life-changing events and ensure they can bring their best and authentic selves to work in good times and bad. My first time supporting a direct through personal challenges was hard, and I feared making it worse.

 

Love Heart Painted on Clustered Hands

 

Managing humans means listening, supporting and treating your directs like humans first, not resources!

 

The best advice I ever received was to treat people like a human first. Since then I’ve learned practical skills such as active listening that support that human first notion. Use your humanity as your driving instinct, and you should be able to support people.

 

I Gotta Feeling

 

With any job move, it can be difficult to generate instincts on your remit. When changing careers, or moving into a new domain it can be difficult to figure out if something is of benefit to the community you serve. I’ve found that moving into DevRel that events have varying target audiences, from developers through to executive levels. It is not always clear-cut who they are aimed at, which events are relevant to which communities and which content would be of interest to those communities.

 

Events have different audiences, and building the spidey sense for which ones appeal to developers is hard. Recommending content and events for audiences that are not the intended target can leave communities uncomfortable. I’ve experienced representing my company at events and being given the sales pitch when the reality is I don’t have the authority to commit to purchases. I’m sure current and former Vice Presidents working as software engineers within financial institutions will all know exactly what I’m talking about. For those unfamiliar, VP is not board-level but the first rung on the promotion ladder. I use that experience and empathy, along with guidance from more experienced colleagues, as the basis of the Litmus test I use to classify developer and non-developer events.

 

Litmus pH Paper Test

 

Much like Litmus paper can identify alkaline and acidic compounds, as advocates we need to form instincts in roles to identify if content is relevant and useful to the community we support and nurture

 

When speaking and writing content, I also need to ensure the topic is something I can speak on as an authentic authority. Much of my experience as a frontend engineer means I use technologies and solve problems primarily with a frontend rose-coloured lens. I can also dabble in domains related to my experience such as Java and Observability given my limited application support experience.

 

I personally will struggle to give concrete recommendations on operational and security topics given my lack of experience and expertise. I try to ensure I give my genuine opinions and experiences of using tools, or how I would use them to solve problems I have previously encountered. I also need to be aware to also share my experiences and guidance on topics such as diversity and technical leadership as well as products of the tech company I represent. I am passionate about being a well-rounded and empathetic software engineer and building others by sharing my experiences and learnings through 11 years of building software.

 

Mother Stands for Comfort

 

Looking back at these experiences, I see merely a subset of the different hats I’ve worn working in the software industry for 11 years. Like my journey through motherhood, all the instincts I have gained through successes, experimentation, failure and reflection. Even now I’m still learning and honing new instincts as I build software and write content. Each new insight helps me to form a gut feeling about what is right or not for me in a given situation.

 

Two Lions Hugging

 

Just like in nature, our instincts for building software and performing our roles evolve through learning and experimentation

 

You may not think you have instincts, especially if you’re worried about being found out as the impostor in your team. Trust me, they are in there! They may not have always been in there since your inception like that mythical motherhood kernel subroutine I searched in myself for at the start of this story. But trust that you can build your own instincts, and use the guidance and help from others to nurture them further. Trust your gut as it evolves over time. And if it doesn’t work out, learn and try again!

 

Thanks for reading! Do reach out if you think of other instincts and lessons you have learned that I too could learn from.

Jump In

Surprising Role Differences Between Frontend Engineer and Developer Advocate

Change is a scary thing. Even with an abundance of preparation, you may be worried if you’ve made the right choice. It’s only with time, and the events in your rear-view mirror that you have the space to reflect on whether it was the right decision. From graduating from school college or university; to moving town or home; to welcoming a new addition to the family; to transitioning jobs and companies; the anticipation and nerves in the pit of your stomach can leave you worried if the leap you’re about to make is worth it.

 

Three months ago, ahead of my first day as a Developer Advocate, I had the same pre-first day butterflies in my stomach that I do with every change. My husband will attest that I am that person who tends to like having a plan or having considered every angle before diving in. I had weighed up my reasons for leaving carefully. I had done my homework on the expectations of this role, and the typical responsibilities of advocacy roles thanks to some great conversations and resources from wonderful advocates like Trisha Gee, Helen Scott and many others. I had researched the company I was due to join and was happy I was joining a strong, friendly and supportive team who would support me along the way. I felt very much prepared and happy with my decision.

We all have that imposter whispering in our ears questioning our decisions. I just imagine mine looks more like the Shame Wizard from Big Mouth!

But then the sly imposter’s voice starts whispering in my ear. Have you missed something? Have you made a mistake? Should you really leave a comfortable spot in the investment bank you’ve been in for 10.6 years for advocacy?

 

Although my experiences of my first conference slot as an advocate gave me an indication, passing my probation and becoming an Elastic Certified Engineer have shown me I enjoy advocacy and am performing well. It also exposed me to many additional differences that I was not expecting despite my meticulous research. Here I share five surprises I’ve encountered in my first 3 months as an advocate, for anyone curious about jumping into advocacy, or even those interested in movement from regulated industries such as banking to tech.

 

Eeep, Where are the Bumpers!

 

This insight is very much specific to my experiences of moving out of a heavily regulated industry. Prior to this role, I spent just over 10 1/2 years working in investment banking. I had worked for the same company since graduating from university. Despite having progressed through the ranks, and undertaken a mixture of tech contribution and leadership roles, I still felt like I was in my first ever grown-up job in some regards.

 

Finance generally is a regulated industry. It might not be apparent when you start, or for this in other industries, but regulation has an impact on the processes and techniques you adopt when building software. Banking, in particular large incumbent investment banks, can adopt processes that, while often necessary, can make getting things done challenging. It’s natural for developers wanting to ship software to find jumping through these hoops frustrating. Often it’s not apparent what the justification for the procedure actually is. Or these processes can feel like archaic and overly-bureaucratic procedures that are maintained in lieu of adopting modern, automated techniques that could produce similar or enhanced controls and faster delivery rates and less aggravation. Sadly towards the end of my tenure, I felt this frustration as some procedures no longer made sense to me, and indeed some colleagues, and seemed to be more driven by other individuals’ aversion to change than as legitimate protection. Yet for the ones that did make sense, they gave you confidence that there were guard rails in place to stop you from doing something you really shouldn’t.

 

Kid Rolling Ball Using Bowling Ramp

 

Moving from a large to small company is a bit like the first time you go bowling as a kid and don’t have the bumpers or ramp

 

Jumping into a tech company that is currently scaling is a large step away. I imagine moving to a small start-up would have been an even larger change. Often many of the processes you took for granted are there are not, or are regularly evolving. This change can feel odd. Much like the first time you go ten-pin bowling with the bumpers (aka those metal barriers that stop you from rolling the ball in the gutters) down as a child. The first few times you’ve visited the alley as a child you might have had the bumpers up, or perhaps the metal contraption, or ramp, to help younger children roll the ball, to help you get a strike. Suddenly not having those aids available can be initially scary and intimidating. You may be fearful to make mistakes or throw a few gutter balls. Thankfully my experience has shown with a supportive team who has welcomed me and answered my myriad questions, after a few throws you’ll adjust and start hitting pins down again.

 

Beware Freedom Paralysis

 

An extension of this lack of bumpers is an abundance of freedom, which you can fear you’ll fail to capitalise on effectively. Most software engineering teams operate today with a rough plan of where they are going. They will have either regular releases or working cadences where they deliver features. Note I purposefully avoided the use of Sprints there people, as Kanban and other frameworks and techniques work for software too! Ideally, teams will adopt a continuous delivery model with knowing what product direction is and developers will feel confident picking up the next feature for development. Your deadlines feel a lot more concrete.

 

Starting out as an advocate requires more exploration, and has a less concrete path. Some of your activities may tie into conference engagements and booth duty for scheduled conference sponsorships with set dates. But much of your learning and initial content generation doesn’t have a set deadline. Furthermore, this deadline isn’t really set by a single individual such as a Product Owner, Product Manager or other tech management. I have a lot more admiration for advocates as I’ve realised you have to be strongly self-driven to generate authentic content that fits the products you advocate for, and then share it in various forms. This can also be even more challenging as many of the advocates I know and work with work remotely or while travelling.

 

Women Confused Shrugging Shoulders

 

I’ve had the issue of having so many ideas that I’m not sure where to start

 

It’s up to you to find your own way and formulate a plan of what areas you want to focus on. Over time I’ve found that so many ideas for content and projects have appeared in my head that I have to note them down somewhere and form a rough plan of what I’m going to focus on for the next few months. Those who know me as the reformed Scrum Master and Agile geek will be happy to know I have a simple private Kanban board to throw these ideas on and evolve them over time.

 

It’s important to also find your niche. You might think your job is simply to showcase the products built by the company you work for. To present engaging content that is interesting to the community, you need to present an authentic voice. Furthermore, it can’t be a simple product pitch that you throw down developers’ throats. I was surprised that I could maintain my passion for frontend development, and use that to frame the topics I share with the world with a sprinkling of the products for which I advocate.

 

Actions Speak Louder Than Titles

 

There are many different titles that people will give themselves within advocate circles. You might have come across individuals calling themselves Developer Advocates, as I do. Others refer to themselves as Developer Evangelists or even Developer Relations. Figuring out the difference between these titles can be confusing, as they largely mean the same thing. However, this community realises that the title is less important than producing content and engaging with a strong community of enthusiastic developers.

 

A wise and experienced advocate once told me I was already an advocate in practice since I was speaking at conferences and sharing blogs with the world. Yet when I decided to add Developer Advocate at Heart to my LinkedIn profile to attract more advocate roles, it felt forced and fraudulent. Part in a way because a lot of the content I had written had more of an agility or engineering manager vibe. However, the main reason for this was the simple fact that the procedures of my prior organisation when reviewing my content left it feeling like unappreciated efforts that aren’t part of my responsibilities as a front-end engineer. Although some were very supportive and gave me strong mentorship, sadly after a while their support was overshadowed by negative views and experiences.

 

Group of Kids Huddled Together Looking Out Over the Sea

 

Irrespective of whether you’re a developer speaking or an advocate, you are still part of a community and able to share ideas

 

Now that I’ve moved onto this role I see what this advocate meant. Much of the skills I have built in speaking, blogging and coding are those that I use now as a Developer Advocate. Even in the first 3 months! Those same skills will be the ones I will continue to build now that I have the title.

 

Spare Time Is Now My Job

 

As an extension to the prior point on actions, I have a stronger appreciation for how amazing it was for me to undertake advocacy in my spare time when it wasn’t technically my job. Prior to becoming an advocate, I spent an inordinate amount of personal time working on my blog or building a talk. In my last role in the bank, I was strongly encouraged to use company time for building out talks. However, working in an organisation where software and technology are a cost rather than a direct sellable asset can mean justifying working on a conference talk over coding up feature X or attending feature Y is difficult as it can be challenging to justify to users who needed that feature last week.

 

By the end of my software engineering tenure, I found that I enjoyed the time I spent tinkering with code examples or writing talks and blogs far more than building the software and following the required procedures to get my changes live. I once had a boss who emphatically proclaimed when I started working for them that they worked to live rather than living to work. When I heard this as a young software developer living with roommates in London without any dependents or cares I found this strange. We were working 40 plus hours per week, with emphasis on the plus for me. For this reason, the idea of spending the majority of my week not enjoying what I do seemed alien.

 

Happy Family Cuddling in the Sun

 

One great advantage of becoming an advocate is that speaking, blogging and coding is my job, leaving my spare time for me to spend with my family

 

Now as a mum and driven technologist I do get the idea that other priorities drove this individual. Our priorities and passions morph and evolve as we progress in our careers. If your side hustle is more interesting than your day job, and it’s viable to make a career out of it, it might be time for a change. I’m still in awe that I get to do the conference attendance and talks that I considered a fun side gig as my job. Pinch me!

 

Still a Developer at Heart

 

One factor that can make those reluctant to change from software development to advocacy is the amount of code. The coder stereotype is that we sit coding frantically all day and hate writing documentation with a passion. With a move to advocacy, there can be a natural concern that you will rarely get to code or tinker with new technologies, languages and frameworks. Instead, you’ll spend all your time building presentation decks and writing thought-leader-style blog posts.

 

Women Looking at Code

 

I’ve been glad to have had the opportunity to write more code compared to some other roles I’ve held in my time

 

I’ve been happy at the amount of code that I’ve been able to write. Part of advocacy is I need to understand how to use the products the company makes available to developers, and by extension, help share this knowledge. I’ve found in comparison to some leadership roles I’ve undertaken such as Tech Lead and Scrum Master that I have written more code in this role.

 

There is a reason that I include developer in my title. Development is still a strong part of my identity. I am still a developer at heart, who advocates for some pretty cool software. Long may that continue!

 

Thanks for reading! Do reach out if you’re interested in finding out more about my experiences, or have any questions.

Should I Stay or Should I Go? (Na na na na na na na na)

Reflections on Engineer Role Moves Within and Across Organisations

So someone has resigned. Read all about it! Suddenly the rumour mill is working overtime as the news of an individual’s impending departure starts to spread through the grapevine like pests hungrily searching for nourishment from this morsel of gossip. Many of us will have conflicting views on this depending on whether we are the recipient of news or the resignee.

 

Lucky Cats Waving

 

Saying goodbye to a company can be hard, but also opens exciting opportunities and fortunes

 

I wouldn’t call myself an expert on developers resigning, but I do have a few thoughts on the resignation versus mobility debate. In my 10.6-year tenure, I’ve resigned twice, retracted a resignation once, moved teams twice, been promoted once, and moved roles several more times within teams. I’ve also seen the other side of the coin, being the manager or lead trying to grapple with the resignation fallout. Throughout my career, I’ve always had a gut feeling that it’s time to move on to something else to scratch the unfulfilled itch in my current role. Sadly I’ve not always acted on it as quickly as I should. But even that inactivity has helped me learn and grow.

 

This rich career tapestry has molded my opinions on whether a hop to another company is always the right call for your career. As I started my latest exciting chapter recently, I share my thoughts on resignations. In this piece, I’ll cover the reasons people, and more specifically engineers, quit; when a move might be a better option for you; and tips for managers on how to handle resignations with grace based on my own experiences on both sides of the table.

 

News of the World

 

Through my own recent experience, I’m come to think of each resignation as a tabloid newspaper. I can sense some eye-rolls will appear as I write this, but hear me out!

 

Bundled Newspapers

 

Resignations are structured similarly to a tabloid newspaper article

 

There are three primary elements of any tabloid newspaper article, at least in the UK where I reside.

 

  1. There is a single bold headline that is the deal-breaker for staying within the role. Now it may not be a catchy pun like those used by many tabloid front pages here in the UK. But it’s normally the 10 words or less tipping point that has led this person to decide it’s time to move.
  2. Those catchy simple headlines are normally prefixed with a more detailed subheading to give a little more information. Here I like to think in resignation terms there may be some smaller niggling things that are not the top reason but have contributed to your rockstar employee wanting to do something different.
  3. Finally, there is the story itself. The opinion piece that any resignee has on how this bigger picture and smaller elements have manifested into a situation.

 

The headline and subtle subplot are all relevant to a resignation. As a manager on the receiving side of resignation, if you’re looking for things to fix in your organisation to eliminate further, you should scruitinise not only the sensational headline but the subtle detail in the subplot. It’s also important to look at common themes across multiple resignations across teams and institutions. Through the great resignation of 2021 and early 2022 personal factors can mean there may not be common themes, but certainly, from speaking to friends and colleagues it’s more common that bugbears that have subtly gnawed at us over time have eventually built up, and the personal circumstances become the final push to send you on your way.

 

She Moves In Her Own Way

 

Managers and leaders always want to have a simple, one size fits all reason for why people leave. Having been on both sides of the table a few times in my career, I know that is not the case. Thinking back to our tabloid analogy, it would be a pretty boring read if every article had the same headline!

 

The most common reason people cite as the silver bullet of resignations is that "good people leave bad managers". At one time I strongly believed this to be the case. I’m sad to admit that at one point it was the source of my sudden pandemic burnout-induced rage quit that forced me to search for a new role. But each story normally has a more nuanced subplot. I’m more inclined to believe that good people leave bad cultures, opportunities, or processes, that can spread within teams, departments, or entire organisations through one or many individuals.

 

Lego Joker and Two-Face

 

We’ve all had good and bad managers, although I hope none of you have worked for these super villains

 

I’ve always agreed with Rands’s principle that at some point a person’s shields go down, and they become open to new opportunities. His piece gives a wonderful set of questions that flow through people’s minds when the potential of a change emerges. I won’t cover this point as he does an amazing job doing so. But for engineers, architectures, and managers with an engineering heart, there are a few recent themes I’ve observed that contribute to a person putting their shields down:

 

  1. Do I get to work with the technologies and frameworks that I’m interested in? Particularly in heavily regulated sectors where adoption of bleeding-edge tech is considered with an immensely strong aversion for risk concerns, developers may become tired of working on old tech and concerned that they may become stuck and unable to progress in the industry.
  2. Am I getting enough time to focus on the contributions that I’m passionate about? This can be outside open source contributions or community contributions as well as within the business that you work for.
  3. Do I feel productive? Are there organisational procedures that I need to follow that I feel impede my ability to get stuff done? Am I struggling with excessively bureaucratic processes? These may also be driven by company culture or political reasons too.
  4. Do I see a clear career path that fits with where I want to go? For engineers that want to stay technical and are not interested in management or people development, companies must provide tracks for technical progression as well as progression into engineering management and other tracks such as design, testing, and agility.
  5. Do I as a developer feel respected by the establishment. In non-tech companies such as banks, health, and ecommerce where the main commodity or service is not software, you still want to feel like part of the team and not an afterthought.
  6. Do the firm values and mission still resonate with me? Have I outgrown these values? Or am I feeling that I am connected to these values, but others are not practicing them in a way that I’m comfortable with?
  7. Are the testing and technical debt practices treated with the same respect as the development of new user-focused features? Are you able to follow industry best practices in these areas? Speaking to some developers over the years, deprioritisation of these themes produces products that become more difficult to add to and maintain over time, leaving them feeling a lack of pride in the products they build.
  8. Do they have the flexibility they want to need when it comes to hybrid or remote working? Sure, some people prefer the office, but the adoption of the office-focused ethos that many companies are adopting at the moment doesn’t work for everyone. Some people want to spend portions of their time working while traveling or visiting family. Some like me find the benefits of home or hybrid working make family life more balanced. If you want to maintain a diverse and talented workforce mandating office attendance in a post-COVID era may put you at a disadvantage for recruiting them compared to more flexible firms.
  9. Yes, salary and perks are also a factor too. Let’s be honest here! Of course, this list is not exhaustive. I’m sure you’re thinking of many other factors based on your career path to date. But any one of these can open up the technical mind to considering a change.

 

Time to Move On(?)

 

When considering a move it’s often the case that we immediately jump to moving to another institution. However, evaluating the potential for an intra-company option might be a good option depending on the reasons you have for leaving. I remember seeing Carla Harris speak a few years ago walking through some of her pearls of wisdom. The one pearl that I still remember vividly was when she discussed the seat versus the house. The seat in this case refers to the role and high-level duties that you perform each day. The house is the institution in which you are working. She implores us to consider in times of career struggle if it is the seat or the house that is the cause of our discontent.

 

Armchair in Sun House

 

When considering a move it might be the role, or seat, in the house that’s not quite right

 

This advice has steered me well for a few years. I stayed in the same firm for 10.6 years and moved seats several times. It was only when I eventually realised that I wanted to take a different direction that wasn’t compatible with the house, that I ended up resigning. To continue the analogy, I could have stayed and worked to remodel the house, aka change the problems. But another lesson I’ve learned from The Liberators Network is that sometimes it’s worth thinking about if you think the fight to change in some situations is worth your time. Beliefs or opinions that are strongly embedded in organisations can be very difficult to change, even if people agree that they should not be there. In the end, if you will exert significant effort and time to rectify the problem that you don’t think is worthy of your time or impacts your personal timelines, it might be best to find another house that can be a home to these ideals and values.

 

A (Person) Worth Fighting For?

 

I’ve seen many engineering managers disagree on whether it’s worth trying to negotiate to keep someone. This applies to moves out of the organisation, as well as internal mobility moves to other teams. I think there are good and bad ways to approach it. Sadly I’ve handled it badly and well for different individuals over the years (apologies to those in the former camp). But in my experiences on both sides of the table, and experiences with amazing and not-so-amazing managers handling my cases, I’m starting to build a blueprint of how the best resignations are handled. Here’s how I think it should go.

 

You should always start by saying congratulations. Acknowledge their good news. This is the true distinction between good and bad managers. A bad manager takes it personally. Most managers immediately go into problem-solving mode, ask a myriad of questions and propose tons of solutions to try to fix the problem. A good manager acknowledges this is good news for the resignee and expresses happiness for them.

 

Congrats Sign

 

Don’t forget to say congratulations!

 

Next, ask them questions about the new role, and really listen to the answers. Find out what is exciting about this new adventure. How does this engagement fit in with their wider career goals? This moment is about the person resigning. It’s easy to jump ahead and think about the hurt you may feel that someone is leaving your team, or how this person leaving impacts how others see you as a manager. You need to be humble and leave your ego at the door. It’s not about you!

 

Discuss why these elements are not present in their current role. Especially if you have been working with this person to identify ways to expose them to these opportunities already. It may be a question of timing or personal circumstances that mean the timing to jump is now.

 

As uncomfortable as it may be, you should discuss compensation and perks offered in their new role. Amid the great resignation, offers are high. Particularly for long-tenured individuals who have not hopped around a lot, there may be a significant jump. Does this help them with personal aspirations? Can you counter? If you are thinking about discussing a counteroffer with management you should also consider carefully if you should as well.

 

Boxing Gloves on Floor

 

Know when you need to lay your gloves down, as not everyone wants to be fought for

 

Ask them if they want to be kept or fought for. This is important as we normally miss this and immediately escalate to keep people, particularly rockstars that you may want to retain. If someone truly has their heart set on leaving, you should respect this decision and support them in their transition. Throwing directors and senior folks at them to convince them to stay can sour the company’s relationship with that individual and make them feel uncomfortable. Not everyone wants to be fought for.

 

It’s Your Move

 

The Great Resignation has meant it has been an employee rather than employer market. In these times companies need the realise that retention of good people should be of equal, if not greater importance than attraction. Larry Fink’s CEO letter hammered home for me that managers, not just CEOs, should be mindful of the various issues facing their people and be thoughtful in how they engage with individuals.

 

In addition to upending our relationship with where we physically work, the pandemic also shone a light on issues like racial equity, childcare, and mental health – and revealed the gap between generational expectations at work. These themes are now center stage for CEOs, who must be thoughtful about how they use their voice and connect on social issues important to their employees. Those who show humility and stay grounded in their purpose are more likely to build the kind of bond that endures the span of someone’s career.

Larry Fink’s 2022 Letter to CEOs

 

Considering this sentiment, even after the resignation, it’s worth keeping in touch after they leave, and leaving the door open for strong people that you enjoyed working with. Leaving for a new company is always a step into the unknown. Although it might be rare, people may want to come back. I don’t have any experience of this, so I suggest reading Helen Scott’s amazing piece on her experience going back to JetBrains which covers this situation well. I agree with her that probation periods are an opportunity not only for employers to evaluate if you are a good fit for the organisation, but also if this institution is a good fit for you and your aspirations.

 

Neon Sign

 

Just as the sign says, I don’t know where I’m going from here, but I promise it won’t be boring

 

Moving companies can be scary. I was at the same establishment for 10.6 years, and it was my first grown-up job after university as well. So of course I’ve been feeling a mixture of excitement and terror. I’m loving the change and challenge a couple of months in. I’ve also been fortunate to connect with old colleagues and community friends at Devoxx UK 2022 as well, which was amazing too. If you’re currently thinking about staying or going it can be an agonising decision. You may be worried about the timing, what will happen if it doesn’t work out, scary thoughts about being found out as the imposter, or even if the perks will leave you and your family at a disadvantage. The best advice I’ve received is not to overthink it. I’m now embracing that sentiment and enjoying the ride!

 

Thanks for reading! Do get in touch if you would like to chat about my moving experiences, or discuss your own. For those who now have The Clash stuck in their head, apologies and enjoy!

Speak Your Mind

The Differences Between Conference Attendance Experience as an Advocate versus Speaker and Attendee

It’s tech conference season! I’m starting to find that there are two busy periods in the year for tech conferences: April-May and October-November. It’s kept me busy as a new developer advocate starting in April 2022.

It’s more of a learn-by-doing approach, just like learning to swim by being dropped into the middle of Loch Ness. However, I wouldn’t have it any other way as I’ve always been more of a learn-by-doing person. My first ever manager referred to this style as “filling your boots”, which means diving in and taking as much as you want. You just need to balance this with not taking too much. Otherwise, you’ll end up in a similar situation to my husband in his youth where his boots filled with mud at a festival and he struggled to escape the field of sludge (sorry honey)!

I have been fortunate enough to speak at several conferences, including Devoxx UK in 2021 and 2022. My first experience was as an engineer with a passion for speaking and the second was as a developer advocate. I’ve enjoyed both of these experiences. I’ve also experienced vendor booth duty at DevOpsDays Birmingham, which was an enjoyable education. Up until now the closest experience I had was attending university recruitment events on behalf of my prior company.

Speaker on stage as seen by the audience

In addition to adjusting from online to in-person tech conferences, I’ve also been adjusting from attendee to speaker and advocate

I can’t help but see some key differences in my conference experience between my different roles. In this piece, I share my comparative experience as an attendee, speaker, and advocate, as well as tips on how to maximise your experience irrespective of your title.

(Not) Guilty

One key difference when attending is an advocate is that you see attending the conference and speaking to people as part of your job. As a general attendee, even though you are representing the company, it can feel like it’s perceived as a bit of a jaunt because it’s not a common activity for you to engage in. Even if you’re a regular meetup attendee, you are going to sessions in your own time at lunchtime and evenings rather than during traditional work hours. So going to a conference during the day when you have a mountain of work to do can leave you feeling a little guilty.

This could partly be dependent on the various factors that have led to your attendance, such as:

  • Whether you paid for your ticket out of your pocket or if it was expensed via your company.
  • If the ticket forms part of a dedicated personal training budget or a centralised departmental pot. I’ve seen where this is held centrally that you are less likely to partake in training outside of internal company offerings.
  • The number and levels of approvals required for conference attendance and speaking. While many start-ups and scale-ups have lighter procedures such as manager approval, larger institutions may have more defined or multi-level approval processes.
  • Any expectations regarding knowledge sharing of what you find out. Some organisations or departments encourage you to share what you find out via internal blogs or knowledge-sharing sessions. One former colleague I bumped into at Devoxx UK was in this situation where they were taking notes so they could share their learnings when they returned to the office to justify the ticket cost.

I’ve always felt the need to maximise the attendance experience as a junior engineer when I’ve committed to sharing my experience internally when I come back to work. It’s understandable to think of this as actual work since it’s a quantifiable contribution. Often as engineers, we dismiss non-contributory efforts such as catch-ups, 1:1s, or admin because it’s not writing code. then when we transition to management, leadership, or even DevRel roles we realise that these contributions are not only valid but what we spend most of our time on. It’s important to drop the guilt, as learning new technologies and hearing about other experiences makes you better at what you do, irrespective of whether that’s engineering, management, or even advocacy. So enjoy!

Bounce Back

As you progress on your speaker journey, you’ll find you become more resilient to handling issues that appear in your talk. Possible issues are false starts, mispronunciations, and technical glitches. I remember vividly how my first-ever issue knocked me off my flow entirely. It was an online evening meetup where I drank all of my tea before my slot, and then ended up trying to curb a coughing fit live on camera with no water or beverage in sight.

Scrabble tiles spelling resilience

As you gain speaking experience, bad things don’t stop happening. You just learn the resilience to take these issues on the chin and keep going

At that moment I wanted to earth to swallow me up. However since that eventful meetup, and through the advice of other speakers, I’ve learned that the secret to conference speaking is not that your session is full of mistakes. It’s that you keep going irrespective of the mistakes that you make. This realisation has helped me adopt a change in mindset. Despite being a pessimistic character, I no longer finish a talk feeling it was a disaster if one little thing went wrong.

I remember seeing the wonderful Gary Fleming at Lean Agile Exchange 2020. I’ve never seen someone so calm under pressure. He started his talk late because of unexpected Zoom issues at the conference. His clicker wasn’t working so he casually through it over his shoulder. Yet he gave one of my favourite talks at that conference. I remember thinking I would never be able to have that confidence to cope with the unexpected. Yet I feel I’m starting to get there.

Pixelated screen

I got through the glitches, whoop!

This year at Devoxx I had a couple of glitches. My HDMI adaptors didn’t play ball, so I borrowed one from the tech gurus. My shiny new clicker with spotlight capability, which I tested at home for 2 weeks prior, kept freezing. So I abandoned it and went between the large screen and my laptop instead. I had a couple of stutters here and there. Not everything was as I practised. Yet I managed to get a couple of audience laughs, and many compliments afterwards too, including from the amazing James Gough who has been a fantastic mentor to me throughout my career. I’m not completely calm under pressure yet, but I’m getting better at hiding it over time.

Connect

Your first time attending a conference on your own can be a pretty scary one, regardless of your role or whether you are speaking or not. You probably won’t know many people at the event. It can be a bit intimidating to try and strike up conversations with people. Especially if you are an introverted character, or are from a diverse demographic. When you feel like you stick out like a sore thumb, you may be reluctant to speak to large groups of people that you don’t know.

As I attend more conferences I’m feeling more confident about connecting with people. Between DevOpsDays Birmingham and Devoxx UK this month I’ve met with many wonderful people, and had so many interesting and insightful conversations. Not all of them are about tech either. I’ve had wonderful conversations with other speakers where we have all shared our tips. Including the aforementioned notion that no speaker is perfect, and it’s that they keep going.

Two men hugging in a crowd

Conferences are great places to connect. It can be hard at first, but you will be welcomed with open arms

It’s not necessarily that I’ve become this super confident person that can walk up to any stranger and chat away. That is still a work in progress. What has changed is that I’m starting to see familiar faces appear at conferences and meetups. These individuals are also kindly introducing me to others so I can expand my network further. Conference communities are always a friendly bunch when you get to know them.

If I’m attempting to speak to people I don’t know without an introduction, I’m learning to ask more about what others do to strike up a conversation as well. Chatting with a friend this week I agree that people love to talk about themselves, so asking questions is a good way in.

Born to Be Wild

What you do in your day job may affect what talks you select to see at the conference. Thinking back to that justification of the ticket price mentioned previously, we may naturally want to pick topics relating to the tech we use every day to ensure we have the practical knowledge to take back to our organisations. Yet we can still learn a lot from attending sessions outside of our comfort zone. Particularly when it comes to identifying emerging tech trends, different opinions, or alternative patterns.

I saw so many wonderful talks at Devoxx UK this year by some fantastic speakers, and not all are strictly related to my elected speciality of frontend development. Some of my favourites were:

  • The opening keynotes I caught gave some wonderful thoughts. Holly Cummins covered the emergence and future of the Java ecosystem with great humour. Asim Hussein clearly explained carbon neutrality and offset definitions in a way that means I finally feel like I understand these definitions.
  • Grace Jansen covered stateful and stateless microservices in a great session that helped me reflect on my prior microservice experiences as an engineer and realise that it’s not as clear cut as having all your services be stateless.
  • I got to see my new colleague David Pilato in action with his FS Crawler and Elastic talk. Given I’m new to the Elastic stack it was great to see a starting example of how to show off the product to developers using a meaningful use case.
  • Taking a glimpse into the secret life of Maven Central with Joel Orlina was great. Although I’ve only used Maven repositories with Gradle in the Java ecosystem I loved the level of transparency he shared in this talk on their scaling challenges, and how they worked with publishers to address these issues.
  • As a JavaScript and Typescript engineer, I was excited to see Alvaro Berruga talk about what’s coming next in JS. I learned more about the proposal process, which was really interesting. Now I know where to find the language proposals too!
  • Going out of the traditional Web stack with Quarkus Renegade with Sébastien Blanc and Stephane Epardaud was an interesting education. I’ll be looking to learn more about Quarkus in the future, hopefully at a London Java Community meetup!
  • I have some experience of Kafka from an enterprise system architecture angle, so it was great to see Danica Fine show a home project using Kafka and senors to give her alerts when her houseplants needed watering. I appreciate the practicality of this approach given my poor track record of keeping plants alive!
  • Martijn Verburg’s session on running Java containers on cloud infrastructure was very insightful, and I appreciated the practical tips on Garbage Collector selection. My prior experience is that GC selection is never considered, and teams always go with the default assigned by the JVM.
  • Seeing nature and software battling it out against each other in the security domain was an enjoyable experience. Well done to Grace Jansen for covering both sides of the battle solo!
  • Learning more from Guy Royse about Redis and RediSearch on an interactive adventure to find Bigfoot was a great experience. This was a wonderful example of using humour and a practical use case to showcase search capabilities. I’m hoping to give Elasticsearch justice in my new role with some of the tips I picked up in this session.
  • Seeing some of the ML approach adopted by Jonas Mayer, Martin Förtsch, and Thomas Endres to respond to and address sh*tposting online was very amusing and insightful. It refreshed me on some ML challenges such as stopwords and training considerations that I hadn’t been exposed to since my university AI course.
  • Seeing Andrew Harmel Law talk about practical tips for capturing the four key metrics from Accelerate was definitely of interest to me as an agilist and frontend engineer encouraging the adoption of data visualisations rather than the usual data grids, as per my own talk slot!
  • Hearing Kevlin Henney’s closing keynote on our attitudes to change in the software we build made me smile. It was great to see that I’m not the only person who has read Your Code is a Crime Scene by Adam Tornhill too!

Of course, I should also call out the social elements like Java Jep’dy, the speaker dinner, and Devrocks drinks on Wednesday and Thursday evenings too. These were great opportunities to have fun and connect with people.

Fairground prizes booth with fireworks

It’s not so often you see a Java game show with big prizes!

I also have a few others I’m awaiting viewing when the playlist goes live:

  • Sadly I missed the start of Julien Dubois’s session on accessibility. As a frontend engineer, I’m wanting to educate myself more on how I can make the things I build accessible to all, so I will definitely be watching this back.
  • Everyone raved about Julien’s session on REST, to the extent that the room filled out. So I’m checking that out when I can!
  • The same goes for the React Micro frontend talk by Rotem Zifroni. I didn’t make it after my talk slot before the doors closed so I’ll be watching that closely to see how closely it mirrors my early experiences of Angular Micro frontends and the potential approaches that can be taken.
  • I really enjoyed the mental health-focused keynote at Devoxx 2021, so will definitely be checking out Frédéric Harper’s session emploring us to not .gitignore mental health.
  • I’m interested to hear Jonathan Rigby’s experiences of metrics mania in his talk when I can. It’s my experience that teams gravitate towards extremes of over-metrification, or not having any metrics at all. So I’m interested to find out if a happy medium is possible.
  • TDD and other drugs was full, and I heard wonderful things. So I will be watching Vanessa Formicola’s session when it comes online.
    I want to hear Anders Norås’s talk on the Marvels of Teenage Engineering. Speaking to him at the conference it sounded like he had many inspiring stories about prominent technologists learning as teenagers, which I find inspiring.

Stop & Listen

Overall I’ve found the experience of attending conferences as an advocate to be an exhilarating and enjoyable one. I’ve met many people from various companies, made connections that will hopefully lead to future meetup opportunities, and also connected with prior colleagues as well.

Scrabble tiles with listen more

As technologists, we should seek out more learning opportunities at meetups and conferences to grow

Irrespective of whether you are a speaker or not, conferences are a great opportunity to grow as technologists, expand your knowledge of frameworks, languages, and tools and connect with others that can educate you and challenge your thinking. These are benefits you can take back to your day jobs, not just by sharing on a blog or a knowledge share session, but also in the development of the software you build. Don’t feel guilty about taking the time to grow!

Thanks for reading! Do get in touch with your own tech conference attendance experience, especially if they differ from mine.