Sherman On Software Latest

  • Writing A Run Book Can Be Your First Iterative Step

    Writing A Run Book Can Be Your First Iterative Step

    Writing a Run Book can be your first iterative step towards mitigating recurring problems.  Recurring problems can cause massive productivity problems, but don’t get fixed because the immediate issue is elsewhere.

    For example, background worker systems rarely fail on their own, instead some unique situation will cause the workers to get stuck, the controller to get confused, or the queue to be poisoned.  Each time, there are really two issues.  The bespoke issue that broke the background processes and the recovery of the background worker system.

    Since each new failure is unique, there is a tendency to treat the background system recovery as a unique problem too.  This increases recovery time and prevents you from learning from past mistakes.  Because the bug isn’t in the background system itself, there is often no motivation to spend time on the code.  Fix the bug, restart the system, and move on with your day.

    Enter the run book.

    Write down the steps needed to mitigate the problem.  This is for humans, so it can be an open ended description of what to look for, it won’t be very programmatic.

    Once you have it, keep iterating.  Add code snippets, descriptions, and flow logic.

    As you iterate, you will notice that some parts of the process can be scripted, or even automated.

    Iteration after iteration, more and more of the run book will become code, which makes it easier to code up the remaining pieces.

    Will you be able to iterate the recurring problem out of existence?  Maybe, maybe not.  But with a run book and a plan, you will make progress and not be waiting for the next outage to wreck your day.

  • The Never Rewrite Podcast, Episode Fifty-Eight, When You Can’t Iterate

    The Never Rewrite Podcast, Episode Fifty-Eight, When You Can’t Iterate

    Isaac and Jeffrey discuss situations where software development teams are pushed to have fewer, larger releases. They highlight the challenges of big release-driven development and the need for careful planning and more QA before each release. They also explore strategies to make the problem less severe, such as minimizing the final push, using an API-first strategy, and feature flagging.

    Watch on YouTube or listen to it at NeverRewrite, Spotify, Apple Podcasts, or Amazon Music, and let us know if you have ever been involved in a rewrite. We would love to have you on the show to discuss your experience!

  • Patterns of Data Loading – Topics and Broadcast

    Patterns of Data Loading – Topics and Broadcast

    Continuing the discussion of the data loading and messaging, this post is going to cover the tradeoffs to consider when working with Topic and Broadcast based systems.

    Directly Consuming Topics Isn’t Really A Thing

    Topics, Pub/Sub, and other one-to-many messaging systems are an extremely interesting and important abstraction, but they don’t overlap with a discussion of data loading.  The message broker will either use a queue for each client, which is covered here (link), or it is a broadcast, without guarantees. 

    Broadcast 

    Broadcast based systems come without guarantees.  The broadcast server sends the message with no idea about how many listeners want the message, or how many that want it, get it.  There is also no guarantee that messages will arrive in order. 

    These systems are designed to minimize the latency and push all of the queuing onto the receiver.  This is when you need to understand your processor’s OSI Layer, implementation.  It’s the rare time that the amount of memory on the network card might be important!

    But, for the purposes of message processing and data loading, all of those details will be abstracted away.

    To the application, things look very similar to running off a queue.  The application has an ordered list of messages, and it needs to process them as quickly and consistently as possible.

    Broadcast doesn’t have message visibility or the risk of double processing.  Instead the pressure comes from internal queue and buffer management.  The messages are on the processor, if they aren’t processed fast enough you will run out of memory.

    Conclusion

    Topic and Broadcast based messaging systems are extremely powerful systems.  When it comes to data loading however, they tend to be a subset of queue processing.

    The need for consistent performance will push your design to the lower right quadrant. 

  • The Never Rewrite Podcast, Episode Fifty-Seven, White Label CRM Updates with Dustin Rea

    The Never Rewrite Podcast, Episode Fifty-Seven, White Label CRM Updates with Dustin Rea

    We check in with Dustin Rea, head of Red Hook Agency, to discuss where White Label CRM is with their ‘turnaround story’ – how they’re handling ‘bug hell’, scaling issues, and what their trajectory is now.

    Watch on YouTube or listen to it at NeverRewrite, Spotify, Apple Podcasts, or Amazon Music, and let us know if you have ever been involved in a rewrite. We would love to have you on the show to discuss your experience!

  • The Other 94%, Why Getting Better At Your Craft Isn’t Economical

    The Other 94%, Why Getting Better At Your Craft Isn’t Economical

    I saw an ad on LinkedIn with the hook “Frustrated by getting 200% better at your craft and only getting a 6% raise?”  The ad seemed to be selling grievances, and a course on becoming a freelance developer.

    What the ad wasn’t doing was disagreeing with the idea that getting 200% better at your primary skill doesn’t make you more valuable or productive.  A 6% raise for improving 200% implies that 94% of your job isn’t your primary skill.  Or that your employer can’t use the marginal value of you getting better.  Becoming a better programmer, by itself, isn’t very valuable to whomever pays your salary.

    The ad was trying to do a sleight of hand: Improve your pay by becoming a freelance developer!  By learning skills that don’t improve your craft!  Being a successful freelancer means learning business, marketing, and sales skills.  The same skills the ad starts off by bashing.

    If someone is paying you to be a developer, chances are that becoming a better developer will have diminishing returns.

    You can be angry, or you can learn about the other 94% of what makes a developer valuable.

    Learn your industry, your company’s business model, and business strategy.  Learn how to be a better teammate, to lead, to inspire, and help others to grow.

  • The Never Rewrite Podcast, Episode Fifty-Six, AI-Driven Testing

    The Never Rewrite Podcast, Episode Fifty-Six, AI-Driven Testing

    Isaac and Jeffrey discuss the potential of AI-driven testing and code generation. They reference an article by Codium AI, which explores the use of AI to generate tests and increase code coverage. While the generated tests may not be perfect, they can serve as scaffolding for legacy code and help identify areas for improvement. The conversation also touches on the idea of using AI to provide business context and legal compliance guidance during code refactoring. Overall, the discussion highlights the potential benefits of AI in improving code quality and reducing risk.

    Watch on YouTube or listen to it at NeverRewrite, Spotify, Apple Podcasts, or Amazon Music, and let us know if you have ever been involved in a rewrite. We would love to have you on the show to discuss your experience!

  • How Running Off A Messaging Queue Impacts Data Loading Strategies

    How Running Off A Messaging Queue Impacts Data Loading Strategies

    Messaging systems don’t change the fundamental tradeoffs involved in data loading, but they do add a lot of opinionated weight to the choices. 

    First, messaging and streaming have a lot of potential meanings and implementations.  To overgeneralize, there are queues, where each message should be read once, topics, where each client should receive each message, and broadcast, where there are no guarantees about anything.

    Queues and topics work as polling loops within your software.  Broadcast messaging comes directly to the machine at the network level; the abstractions are highly dependent on implementation.

    For the rest of this article I’m going to cover queues.  I’ll cover topics and broadcast in future articles.

    Loading Patterns with Queues

    The main feature of a message queue is that you want each message to be processed exactly once.  This requires clients claim messages when taking them off the queue, notifications back to the queue when messages have been processed, and a client timeout, after which a claimed message will reappear at the head of the queue.

    A client has to connect to a queue, ask for some number of messages and indicate how long it will wait for the max number.  For example, AWS’ SQS the defaults are 10 messages or 30 seconds.  The client will block until 10 messages are available, or it has been waiting for 30 seconds.

    Set the message request too big and you will wait while the queue fills.  Set the timeout to long and the first few messages will get stale while the client waits.  You need to balance the time cost of polling the queue against the cost of having your workers idle.

    The main concern however, is visibility timeouts.  If your client grabs 10 messages and has a 30 second timeout it absolutely must finish all 10 in under 30 seconds.  After 30 seconds the unacked messages will be released to the next waiting worker and your message will be processed twice.

    Optimizing worker counts, polling settings, and timeouts requires maximizing execution consistency.  When working at scale, how long an action takes matters much less than how consistent the timing is.

    The Four Patterns of Data Loading are all about tradeoffs.

    If your system is drinking from a firehose, you need to push everything towards a Pre-Cache model.  Pre-Cache pushes data loading out of the critical path, which gives the most consistent timing for message processing.

    Having fully Pre-Cached queue processors is rarely possible, there is too much data and it changes to often.  Read Through Caching is the practical alternative.

    Link Tracking Example

    Link Tracking, recording when someone clicks on a link, is a common activity for Marketing SaaS.  I’m going to use a simplified version and walk through each of the data patterns.

    At a high level, we have a queue of events with 4 pieces of data that describe the click event: Customer Name, URL, Email, and Timestamp.  

    We want to process each event exactly once, as quickly as possible, and we don’t care about the order messages are processed.  However, we can’t insert directly, we need to normalize Customer Name, URL, and Email into customerId, urlId, and emailId.

    Lazy Load

    The nice things about the Lazy Load pattern is that it starts quickly and is simple to understand.

    Unfortunately, every event requires 3 trips to the database to normalize the data.  This adds load to the database and has highly variable processing time.

    It’s a fine place to start, but a terrible place to stay.

    Pre-Fetch

    The Pre-Fetch pattern separates fetching the data into a separate step from execution.  In this example, the worker would be attempting to normalize multiple events at the same time.  Once an event has been fully normalized, it is inserted into the database.

    Pre-Fetch adds a lot of complexity because the workers now have internal concurrency in addition working in parallel with each other.  This might be worth it if the data was being composed from different resources in a micro-service architecture and the three calls could be done in parallel.  In this example though, you would be pounding the database.

    Pre-Cache

    The great thing about a Pre-Cache model is that there are no reads against the database during processing.  It is read-only during init, and write only from the queue.  That will really help the database scale!

    Pre-Cache is impractical in this use case though.  We might know the full set of customers at startup, but urls and emails are open ended.  Pure Pre-Cache setups require that all of the data be known before starting.  That can work for things like file imports and trading systems,  but not link tracking.

    Read Through Cache

    The Read Through Cache Pattern is likely to be the best option for our use case.  It is more flexible than the Pre-Cache Pattern and much friendlier to the database than Lazy Loading or Pre-Fetching.  It pushes complexity to the cache where there are lots of great solutions.  Most languages have internal caching mechanics, and external caches like memcached and redis are widely supported.

    Conclusion

    Reading from message queues is a common problem and usually requires composing data from a database.  What’s the best way to load the data?  As always, the right data loading pattern depends on a your conditions and assumptions.  

    Lazy Loading is always a decent place to start because it is simple.  Performance, cost, and scaling constraints will push your design towards Read Through Caching and Pre-Caching.  Pre-Fetch models are likely to be more effort than they are worth because they add a second source of concurrency and complexity.

    Remember, requirements change over time, so will the best solution to your problem!

  • The Never Rewrite Podcast, Episode Fifty-Five, Writing Your Job Out Of Existence

    The Never Rewrite Podcast, Episode Fifty-Five, Writing Your Job Out Of Existence

    Isaac and Jeffrey discuss the mindset of writing your job out of existence. They explore the idea that being irreplaceable can be a trap and that making your current role disappear in a positive way is the key to career growth. They share examples of individuals who get stuck in repetitive tasks and fail to see the opportunity to transform their work. The conversation highlights the importance of reframing problems as opportunities for improvement and the need to overcome the fear of change. They also touch on the issue of intentionally not fixing problems to protect one’s job.

    Watch on YouTube or listen to it at NeverRewrite, Spotify, Apple Podcasts, or Amazon Music, and let us know if you have ever been involved in a rewrite. We would love to have you on the show to discuss your experience!

  • For Better Iteration, Imagine Heaps, Not Queues

    For Better Iteration, Imagine Heaps, Not Queues

    A new project arrives, you gather the team, and start planning.  You talk through the requirements, write up the work, and put it in order.  Then you iterate!  Repeatedly work on the first task in the queue and keep going until the queue is empty.

    Iterating off of a queue sounds iterative, it’s right there in the description.  But it misses the mark because it ignores everything learned from implementing each piece of work.

    Instead of imagining a work queue, envision a heap. With a heap, you are only guaranteed that the top element is most important.  That’s it, the top, and the rest.  Critically, when you take the top piece of work, you have to sort the heap.  A heap forces you to consider what you’ve learned and apply it to determine what comes next.

    An iterative process requires constant re-evaluation.  There’s the current most important step, and a heap of work.  Iterating off a perfect work queue is a sirin song, an illusion and a trap.  To iterate, learn, and apply your learning, after every step.

  • The Never Rewrite Podcast, Episode Fifty-Four, Shadow Your Colleagues

    The Never Rewrite Podcast, Episode Fifty-Four, Shadow Your Colleagues

    Jeffrey and Isaac discuss how to get started with shadowing people and solving their problems. They share their experiences and strategies for shadowing, including reaching out to the people you want to shadow, observing their tasks, and identifying areas for improvement. They emphasize the importance of shadowing during the onboarding process and the value of asking questions and challenging existing processes. They also highlight the benefits of building relationships and earning credibility by solving problems for others.

    Takeaways

    • Shadowing people and solving their problems is a great way to learn and make a positive impact in a new role.
    • During the onboarding process, take the opportunity to shadow and observe how people work.
    • Ask questions and challenge existing processes to identify areas for improvement.
    • Building relationships and earning credibility by solving problems for others is crucial in the workplace.

    Watch on YouTube or listen to it at NeverRewrite, Spotify, Apple Podcasts, or Amazon Music, and let us know if you have ever been involved in a rewrite. We would love to have you on the show to discuss your experience!