Harry Bailey

Harry Bailey is a technology and delivery leader who specialises in turning agency project chaos into clarity. With more than twenty years of experience as a developer, agency founder and fractional CTO, he helps digital and creative agencies build stronger engineering and delivery cultures and improve commercial outcomes. He focuses on practical, immediately actionable strategies, not theory, so teams can ship work on time and with less drama.

Thoughts on stand-ups

Stand-ups are used by most creative and digital agencies. Teams have daily meetings where they align around their progress, challenges and discuss what’s coming next.

At least 15 minutes a day is spent on those calls. The whole team attends. Listening is the primary activity for attendees. It shouldn’t be controversial to state that the time should be used wisely.

But what does wisely mean? Well for me it means that it’s a good use of time for all who attend. From the most experienced to the least experienced team member. No matter what the role. Everyone should walk away believing they benefited from the call.

The focus of these stand-ups however is all too often a turn taking exercise where an individual’s status is shared. They read out information that is stored in accessible digital tools that the team can access.

What if stand-ups were about planning instead of reporting?

Continue reading

Elastic Beanstalk crons on multi-instance environments

Wow. What a lot of pain.

Updated 6th October 2025 to reference new token requirement for loading instance meta data

So let me first confirm what won’t work. Whether Apache 1, Apache 2, leader_only or EB_IS_COMMAND_LEADER testing, you cannot consistenty get exactly one (not zero, or 2+) instances to run a cron job over a long period of time.

The issue is the the leader information isn’t safe. It’s only available during deployments, when you usually first set up the cron job. But when an instance replacement happens—for whatever reason—there is no related deployment, the test to check if the new instance is the leader fails, and you end up with no crons.

So for anything you do at the moment of deployment—database migrations, logging, whatever— that you only want to run once, even on multi-instance environments in an Elastic Beanstalk Application, you can use and trust the leader tests available to you.

But for anything you want to run regularly, on a schedule across weeks and months, you cannot trust those options.

After a lot of research, and trial and error there are two options available to you.

Worker environments

The ‘official’ way is probably via a worker environment. Essentially an instance set up specifically to schedule and run short or long lived processes.

You can learn more about them via the links below, but for the rest of this article we’ll be talking about the alternative option of ‘runtime leader testing’.

https://medium.com/@joelennon/running-cron-jobs-on-amazon-web-services-aws-elastic-beanstalk-a41d91d1c571

Runtime leader testing

This option means running the cron on every instance of an environment, but the initial section of the code being run checks the if the instance id that it’s running on is the first to be returned in the list of all instances. That is, only the first instance id returned by the aws elastic beanstalk api will continue to run the task.

Below the examples are in PHP, but it’s a valid method for other languages too.

We’re assuming you’ve already set up a cron and know how to alter it to make it run on all instances of your environment.

The steps in this guide:

  • Create an IAM user just for this process and give it limited read permissions
  • Add the credentials to EB configuration
  • Write code to check the instance id from the api against the current instance id

Adding the user

  • Open IAM in AWS console
  • Click Users
  • Click Add users
  • Type your User name – we used “[applicationCode]-eb-read-user”
  • Click the ‘Access Key’ access type
  • Click Next: Permissions
  • Click the ‘Attach existing policies directly’ tab
  • Type ‘AWSElasticBeanstalkReadOnly’ and select it
    • NB: This permission actually gives more access than is required and you could trim it further
  • Click Next: Tags
  • Click Next: Review
  • Click Create user
  • Take a copy of the KEY and SECRET

Storing the key and secret in the environment

  • Open your environment
  • Click configuration
  • Click ‘edit’ on the ‘Software’ section
  • Add two new items, one for the key (examples use AWS_KEY) and one for the secret (examples use AWS_SECRET)

The code

So this is php, but the basic idea is:

  • Install the aws library – here we use composer
  • Add some code to call the library
  • Compare the first returned instance id against the id of the instance running the code

Install the aws library

$composer require aws/aws-sdk-php

Add the code to do the check

$client = ElasticBeanstalkClient::factory([
    'credentials' => [
        'key' => $_ENV['AWS_KEY'],
        'secret' => $_ENV['AWS_SECRET'],
    ],
    'region'  => '[[your region]]',
    'version' => 'latest'
]);

Replace [[your_region]] above with your own

$result = $client->describeEnvironmentResources([
    'EnvironmentName' => '[[your_environment_name]]'
]);

Then load in the current instance’s id. We first need a token using the special reserved IP address of 169.254.169.254.

// Create a stream
$opts = [
    "http" => [
        "method" => "PUT",
        "header" => "X-aws-ec2-metadata-token-ttl-seconds: 21600"
    ]
];
$context = stream_context_create($opts);
$token = file_get_contents('http://169.254.169.254/latest/api/token', false, $context);

$opts = [
    "http" => [
        "method" => "GET",
        "header" => "X-aws-ec2-metadata-token: " . $token
    ]
];
$context = stream_context_create($opts);

$currentId = file_get_contents("http://169.254.169.254/latest/meta-data/instance-id", false, $context);

Then compare the API’s first result to the current one. If the same, so something, otherwise don’t.

if ($currentId == $result['EnvironmentResources']['Instances'][0]['Id'])
{
    // do something. Only one instance will get here
}
else
{
    // don't do anything. All other instances will be here
}

Other useful resources:

https://rotaready.com/blog/scheduled-tasks-elastic-beanstalk-cron

Three hours to trialling new ways of working

The premise of all my work is impact. Agencies look to me for swift solutions to urgent problems. There is rarely time available to building rapport with a team. I have to build trust rapidly as I go.

And that’s not a simple challenge. The approach isn’t possible without a minimal level of trust, but I’ve yet to justify specific time for trust building.

How quickly can I get from meeting a team for the first time, to having their commitment to experiments aimed at improving shared ways of working?

It’s been an interesting challenge finding out.

I’ve used a similar approach a few times now when meeting a new team. I’m putting it out in the world as another opportunity to review it for potential improvements, and to open it up to feedback from those who have relevant experiences and insights.

Continue reading

Why agency teams hate retrospectives – and what to do about it

Most agency teams hate retrospectives. The hour or more spent reviewing the sprint or project they’ve just completed doesn’t do what it promises, and the delivery team can often think of 100 better things to use their time on.

I realised this several years ago. Retrospectives are about a team inspecting current ways of working and adapting them to remove the failures or impediments, but who they’re not great for is:

  • Agencies who change teams around often (dynamic teaming / fluid teaming)
  • Teams who haven’t worked together long
  • Teams who haven’t experienced success at improving their own approach to work

Even when the session goes well, the outputs of retrospectives are often unwieldy, badly defined and so nobody wants to take ownership of the actions.

The actions themselves are never as important as the endless billable work, and so nobody encourages the changes to happen — unless something falls over / fails badly.

The alternative is the micro retrospective. It helps teams who aren’t currently achieving ongoing improvement to dip their toe in the water and experience success with it.

They may then move on to a more detailed form of ongoing improvement once they build the muscle up.

I wrote more about micro retrospectives on the Agency Tactics blog. I’d love to know what you think.