Review, refactor, document, debug β AI pair-programming for every part of the dev cycle.
Analytics Strategy Business type, key Design the analytics strategy.
Automation Process, current Analyze the automation opportunity.
Security Risk Organization, assets, Conduct a security risk assessment.
Technical Project, team, Translate the project into technical 10 user stories + non-functional Requirements timeline, challenge requirements.
No-Code Product idea, user, Design the no-code architecture.
Integration Systems, goal, Design the integration architecture.
Analytics Product type, current Design the product analytics 20 events to track + user property Architecture setup, key question, architecture.
Cloud Cloud provider, Audit the cloud architecture.
AI Strategy & Use case, maturity, Design the AI strategy.
Technical Hiring Team size, roles, Design the technical hiring framework.
Debug this problem systematically. Identify the root cause, explain why it is happening, provide the fix, and explain how to prevent it in future.
Design the high-level architecture for this system. Cover components, data flow, scaling strategy, and key design decisions.
Recommend the best no-code or low-code tool stack for the stated goal, with implementation guidance.
Design the complete analysis approach for the stated question. Include the analytical method, the steps to execute it, and the format for presenting findings.
Plan the complete API integration including the data flow, error handling, authentication, and testing strategy.
Design the complete automation workflow. Map the trigger, steps, conditions, and actions. Include the fallback for when automation fails.
Create a practical cybersecurity checklist and implementation guide tailored to the stated entity and concern.
Write a complete Product Requirements Document for the stated feature or product.
When you need production-ready code fast, not just a working snippet.
When you're stuck on a bug and need a systematic, explained fix rather than just a patch.
Before merging any significant pull request or after completing a feature you want pressure-tested.
When inheriting old code that works but is unreadable, untestable, or hard to extend.
When building a non-trivial feature from scratch and wanting to think through architecture before writing code.
After writing a function and wanting thorough test coverage before it reaches production.
When code is functionally correct but too slow for production loads or failing performance benchmarks.
When integrating a third-party API and wanting production-quality code with proper error handling from the start.
When designing or auditing a database layer for a new or growing system.
After writing a function or module that others will use β documentation written at the time of coding is always better than documentation written later.
Before deploying user-facing or data-handling code β security reviews catch issues that functional testing misses.
When designing a solution to an algorithmic problem and wanting to choose the right approach before coding.
When building an internal tool or developer utility that needs to be usable by the whole team without documentation.
When building input validation, parsing logic, or search patterns where precision matters.
When porting a codebase to a new language, framework, or major version.
When onboarding a new team member or starting a new project β good setup documentation prevents hours of environment debugging.
Before writing a single line of a new system β architecture decisions are the most expensive to change later.
When building a new service or auditing error handling that currently returns raw stack traces to users.
When starting a new project or doing a quarterly maintenance pass on an existing codebase.
When reviewing someone else's code, learning a new codebase, or preparing to explain code in a meeting or review.
When preparing for system design interviews or designing a new system from scratch.
When planning a monolith-to-microservices migration or designing a new system with service boundaries.
When choosing a database for a new project or evaluating whether the current database can support planned growth.
Before building an API that others will integrate against β good design prevents years of backwards-compatibility debt.
When database load is high, API latency is unacceptable, or the system cannot handle current read traffic.
Before going to production with any system that must meet availability commitments.
When designing asynchronous workflows, decoupling services, or building event sourcing into a system.
When the current system is hitting limits and you need a structured plan to scale it without a full rewrite.
When the team is growing and the current repo structure is causing friction.
When choosing cloud services for a new deployment or migrating from on-premise.
When designing or reviewing the entry point of a distributed system.
When building any system where user identity and permissions matter β which is almost every system.
When building a new data pipeline or diagnosing why an existing one is unreliable or too slow.
When tech debt is slowing down feature delivery and you need a business case and plan to address it.
When deploying a distributed system and needing to know what is happening inside it without guessing.
Before any production system goes live β disasters always happen at the worst possible time.
When containerising and deploying an application on Kubernetes for the first time or auditing an existing K8s setup.
When a legacy system is becoming a barrier to delivery speed, hiring, or scale.
When provisioning cloud infrastructure and wanting reproducible, version-controlled deployments.
Before any significant engineering work β a good spec prevents rework, aligns stakeholders, and forces clear thinking.
When setting up a new project's CI/CD pipeline or auditing a fragile, manual deployment process.
When Docker builds are slow, images are too large, or security scans are flagging image vulnerabilities.
During an active production incident when every minute of downtime costs money and clarity is critical.
When setting up GitHub Actions for a new project or improving an existing workflow that's slow or flaky.
When deploying a new application to production and needing visibility from day one.
When a Kubernetes workload is misbehaving and you need a systematic path to diagnosis rather than random kubectl commands.
When cloud costs are growing faster than revenue or when preparing for budget season.
When deploying a system that serves live traffic and any downtime has business or user impact.
When security is only reviewed manually before releases and you need to shift it left into automation.
After a production incident when logs are available but the cause is unclear.
When provisioning the same infrastructure pattern across multiple environments or teams.
When formalising reliability commitments and creating a shared language between engineering and business.
When formalising on-call responsibilities or when on-call engineers are solving the same incidents repeatedly without capturing the solution.
When setting up a local development environment that mirrors production and works consistently across team members' machines.
When engineering productivity is declining as the company scales and there is no dedicated platform function.
When secrets are currently stored in environment variables, config files, or .env files committed to git.
In the week before any production launch β this checklist prevents the most common first-day production failures.
After a system has basic resilience patterns in place and you want to validate they work under real failure conditions.
When trying to objectively benchmark delivery performance and identify what to improve first.
Before going to production with any system that holds data you cannot afford to lose.
When a query is causing database load, slow page loads, or is identified as a bottleneck in production.
When starting a new application and designing the data model β good schema design is 10x harder to fix retroactively.
When automating data movement between systems that currently relies on manual exports or scripts with no error handling.
When evaluating a NoSQL solution or designing a model for a system with known access patterns.
When data quality issues are causing downstream reports or ML models to produce wrong results.
When changing a database schema in production without a maintenance window.
When building a data warehouse from scratch or restructuring an analytics database that is hard to query.
When implementing a specific Redis pattern and wanting production-quality code with proper key design and error handling.
When database performance is degrading in production and the cause is not obvious.
When decomposing a monolith into microservices and the shared database pattern must be broken.
When building a system that must react to events in real time rather than batch processing them.
When experiencing database connection errors under load or seeing 'connection pool exhausted' errors.
When regulatory requirements, data quality issues, or organisation scale demand a formal approach to knowing what data exists and who can access it.
When building a SaaS application that serves multiple customers and must ensure strict data isolation.
When building or restructuring analytics transformations using dbt.
When database LIKE queries are too slow or too limited, and users need real search functionality.
When planning a data warehouse migration that must preserve data integrity and cannot afford significant downtime.
When exploring graph databases for a use case with complex relationships that are hard to query relationally.
When storage costs are growing, compliance requires data retention policies, or users need a right-to-erasure implementation.
When building AI features that require semantic similarity search or retrieval-augmented generation.
Before building any API endpoint β a spec agreed on before coding prevents integration rework.
When designing a GraphQL API for a data-rich domain where clients need flexible queries.
When building a platform that needs to notify external systems about events in real time.
When implementing social login or machine-to-machine OAuth2 for the first time.
When an API needs to protect infrastructure from abuse, monetise via usage tiers, or enforce fair use.
After designing or building an API that external or internal developers will consume.
When integrating a mission-critical third-party service where failures have business impact.
When an API must evolve without breaking existing integrations β which is always.
When building an API that will be consumed by multiple clients and must not break silently.
When your API is being consumed by multiple clients and you want to reduce integration friction.
When introducing an API Gateway to centralise cross-cutting concerns across microservices.
When building any state-changing API operation where duplicate requests must be safe β especially payments.
When synchronous REST is too slow or inefficient for the use case (e.g., long-running jobs, live updates).
When frontend and backend teams work in parallel and front-end needs a realistic API before the real one is built.
When you need to understand how your API is being used, who is using it, and where it is failing.
Unary vs. Server Streaming vs. Client Streaming vs. Bidirectional streaming for each operation, (3) error handling using gRPC status codes (and when to use metadata for error details), (4) [LANGUAGE]
When productising an API for external consumption and needing both technical and commercial design.
Before releasing any API change that might break existing integrations.
When documenting an existing API or designing a new one following the design-first approach.
When building a public API where inconsistent errors confuse developers and slow integrations.
At the start of any ML project β framing the problem correctly prevents months of building the wrong model.
Before training any model β feature quality determines model quality more than algorithm choice.
When starting a new ML project and needing to choose the right model family rather than defaulting to deep learning for everything.
When building an LLM-powered feature and wanting production-grade code rather than a notebook prototype.
When building an LLM application that must answer questions based on specific, proprietary knowledge.
When taking an ML model from notebook to production and needing the infrastructure to maintain it.
Before deploying any ML model β evaluation done correctly prevents shipping a model that looks good on metrics but fails in production.
When an LLM integration is producing inconsistent or low-quality outputs and the model choice is not the problem.
After deploying an ML model to production β models decay silently without monitoring.
When considering fine-tuning an LLM and wanting to evaluate whether it's justified before investing compute and time.
Before deploying any AI system that makes decisions affecting people.
When moving from a Jupyter notebook experiment to a reproducible, automated training script.
Before replacing a production model with a new version β gut feeling is not sufficient for models that affect users.
When building a supervised ML dataset from scratch and needing to maximise label quality and efficiency.
Before deploying or after encountering reliability issues in an ML system.
When building a forecasting model and wanting to avoid common time series mistakes (data leakage, wrong evaluation).
When building a personalisation feature that must work even for new users with no history.
When building an NLP feature that processes real user text and must handle domain-specific language reliably.
When AI costs are growing faster than revenue or when preparing an AI cost budget.
When preparing for ML engineering interviews.
When feeling stuck in career progression and needing a structured plan rather than random learning.
When code reviews are inconsistent, creating friction, or not catching meaningful issues.
When preparing for technical interviews and needing a structured plan rather than random LeetCode grinding.
When writing technical documentation that must influence decisions, teach others, or be a permanent record.
When transitioning from an individual contributor to an engineering manager role.
When setting up a new machine or optimising an existing environment that feels slow or clunky.
Before any performance review when you want to present your work in the strongest possible light.
When spending time re-solving problems you've solved before because you didn't document the solution.
When wanting to break into a new technology, demonstrate skills to employers, or give back to the community.
When preparing for any compensation negotiation β preparation is the only negotiation advantage that's completely in your control.
When a team is struggling with velocity, attrition, or morale and you need a structured diagnosis.
When presenting technical work to an audience and wanting to be understood and remembered.
When building an engineering culture intentionally rather than letting it emerge by accident.
When technical debt is slowing delivery and you need budget or time to address it.
When a developer is feeling consistently overwhelmed, disengaged, or running on empty.
When building an engineering team and wanting a structured, fair, and effective hiring process.
When onboarding a new engineer and wanting them to be productive and confident within 30 days, not 90.
Before facilitating any team retrospective where you want real insights and real actions, not performative exercises.
When preparing for a staff engineer promotion and needing to build both the impact and the evidence.
When there is more tech debt than time to fix it and you need a defensible prioritisation framework.
When building a security hardening plan for an existing application or establishing secure defaults for a new one.
Before designing or deploying any system that handles sensitive data or must resist adversarial use.
When implementing any cryptographic function β home-grown crypto is notoriously error-prone.
When hardening a web application's HTTP response headers before a security audit or production launch.
Before any security incident occurs β response plans written during an incident are too slow and too chaotic.
When commissioning or conducting a penetration test and wanting a structured, professional approach.
When building or auditing an application that handles personal data from users in regulated regions.
When designing or modernising network security for a remote or cloud-native environment.
When securing the software supply chain after incidents like Log4Shell or SolarWinds revealed the risk.
When auditing a codebase for leaked credentials or setting up prevention after a secrets leak.
When preparing for a SOC 2 audit for the first time or closing gaps from a previous audit.
When conducting security-focused code reviews or training developers to self-review for security.
After a cloud deployment or as a scheduled quarterly security review.
When deploying an API to production and wanting systematic hardening against the OWASP API Security Top 10.
When scaling security beyond a central security team to embed it in every engineering team.
When a public-facing application needs protection against availability attacks.
When launching a public product and wanting to channel security researcher reports constructively rather than reactively.
When building security visibility into a system or organisation for the first time.
When a startup needs to demonstrate security maturity to enterprise customers or investors without a large security budget.
When building or auditing any system that touches payment card data.
Before building a complex UI feature β component architecture planned upfront prevents expensive refactors.
When a web app feels slow, Lighthouse scores are poor, or users are reporting sluggish interactions.
When building a React Native feature that must work perfectly on both iOS and Android.
When building or auditing UI components that must comply with accessibility standards or reach all users.
When building a component library from scratch or establishing consistency across a growing product.
When state management is causing bugs, performance issues, or is simply growing too complex.
When mobile app performance is causing user complaints or low app store ratings.
When adding offline capability, push notifications, or home screen installation to a web application.
and Storybook + Chromatic setup. WHEN TO USE: When building a robust frontend test suite that catches real bugs without becoming a maintenance burden.
When starting a new mobile project and needing a defensible framework choice before committing to a stack.
When adding motion to a product and wanting it to feel cohesive, professional, and fast.
When building complex forms and wanting to handle validation, async checks, and accessibility correctly from the start.
When setting up frontend deployment automation that runs quality checks before anything reaches production.
and when not to use with examples, (2) React.memo β which components to wrap and the footgun of object/function props, (3) code splitting with React.lazy and Suspense, (4) list virtualisation with rea
When starting a mobile app and wanting a consistent, scalable architecture from day one.
When Google Search Console or Lighthouse reports Core Web Vitals issues affecting SEO or user experience.
Before submitting an app to the App Store or Play Store for the first time.
When adding multi-language support to an application or planning for it from the start.
When a mobile app handles sensitive financial, health, or authentication data and must resist device-level attacks.
When deploying a frontend application that must be observable in production.
When engineering needs a clear direction that aligns the team and informs product roadmap decisions.
When managing engineers and wanting 1:1s that are substantive, not just status updates.
When miscommunication between engineering and other functions is slowing delivery or creating frustration.
When building a formal mentorship structure or improving an informal one that isn't producing development outcomes.
When introducing or improving OKRs in an engineering organisation.
When managing a difficult situation that requires communicating bad news or delays to non-technical stakeholders.
When team structure is creating bottlenecks, unclear ownership, or slow delivery.
When making a significant architectural decision that future team members should understand without tracking down the original decision-maker.
Before any significant all-hands or large-audience engineering communication.
When scaling an engineering team and wanting consistent decision-making without centralised control.
Before any high-stakes conversation where the outcome matters and the wrong approach could damage trust.
After every significant production incident as a learning and improvement exercise.
When presenting a roadmap to multiple stakeholders with different information needs.
When feedback in the team is either absent (too polite) or destructive (too harsh) and trust is suffering.
Before acquiring, partnering with, or significantly depending on another organisation's technical capabilities.
When building a consistent, fair hiring process that produces better hiring decisions at scale.
When starting a new engineering leadership role or preparing a new leader to succeed.
Before presenting any significant engineering budget request to leadership or a board.
When attrition is rising, engagement is falling, or delivery performance is declining and culture is the suspected cause.
When being promoted to or starting a tech lead role for the first time.
When you need production-ready code fast, not just a working snippet.
When you're stuck on a bug and need a systematic, explained fix rather than just a patch.
Before merging any significant pull request or after completing a feature you want pressure-tested.
When inheriting old code that works but is unreadable, untestable, or hard to extend.
When building a non-trivial feature from scratch and wanting to think through architecture before writing code.
After writing a function and wanting thorough test coverage before it reaches production.
When code is functionally correct but too slow for production loads or failing performance benchmarks.
When integrating a third-party API and wanting production-quality code with proper error handling from the start.
When designing or auditing a database layer for a new or growing system.
After writing a function or module that others will use β documentation written at the time of coding is always better than documentation written later.
Before deploying user-facing or data-handling code β security reviews catch issues that functional testing misses.
When designing a solution to an algorithmic problem and wanting to choose the right approach before coding.
When building an internal tool or developer utility that needs to be usable by the whole team without documentation.
When building input validation, parsing logic, or search patterns where precision matters.
When porting a codebase to a new language, framework, or major version.
When onboarding a new team member or starting a new project β good setup documentation prevents hours of environment debugging.
Before writing a single line of a new system β architecture decisions are the most expensive to change later.
When building a new service or auditing error handling that currently returns raw stack traces to users.
When starting a new project or doing a quarterly maintenance pass on an existing codebase.
When reviewing someone else's code, learning a new codebase, or preparing to explain code in a meeting or review.
When preparing for system design interviews or designing a new system from scratch.
When planning a monolith-to-microservices migration or designing a new system with service boundaries.
When choosing a database for a new project or evaluating whether the current database can support planned growth.
Before building an API that others will integrate against β good design prevents years of backwards-compatibility debt.
When database load is high, API latency is unacceptable, or the system cannot handle current read traffic.
Before going to production with any system that must meet availability commitments.
When the current system is hitting limits and you need a structured plan to scale it without a full rewrite.
WHEN TO USE: When the team is growing and the current repo structure is causing friction.
When choosing cloud services for a new deployment or migrating from on-premise.
When designing or reviewing the entry point of a distributed system.
When building any system where user identity and permissions matter β which is almost every system.
When building a new data pipeline or diagnosing why an existing one is unreliable or too slow.
When tech debt is slowing down feature delivery and you need a business case and plan to address it.
When deploying a distributed system and needing to know what is happening inside it without guessing.
Before any production system goes live β disasters always happen at the worst possible time.
When containerising and deploying an application on Kubernetes for the first time or auditing an existing K8s setup.
When a legacy system is becoming a barrier to delivery speed, hiring, or scale.
When provisioning cloud infrastructure and wanting reproducible, version-controlled deployments.
Before any significant engineering work β a good spec prevents rework, aligns stakeholders, and forces clear thinking.
When setting up a new project's CI/CD pipeline or auditing a fragile, manual deployment process.
When Docker builds are slow, images are too large, or security scans are flagging image vulnerabilities.
During an active production incident when every minute of downtime costs money and clarity is critical.
When deploying a new application to production and needing visibility from day one.
When a Kubernetes workload is misbehaving and you need a systematic path to diagnosis rather than random kubectl commands.
When cloud costs are growing faster than revenue or when preparing for budget season.
When deploying a system that serves live traffic and any downtime has business or user impact.
When security is only reviewed manually before releases and you need to shift it left into automation.
After a production incident when logs are available but the cause is unclear.
When provisioning the same infrastructure pattern across multiple environments or teams.
When formalising reliability commitments and creating a shared language between engineering and business.
When formalising on-call responsibilities or when on-call engineers are solving the same incidents repeatedly without capturing the solution.
When setting up a local development environment that mirrors production and works consistently across team members' machines.
When engineering productivity is declining as the company scales and there is no dedicated platform function.
When secrets are currently stored in environment variables, config files, or .env files committed to git.
In the week before any production launch β this checklist prevents the most common first-day production failures.
After a system has basic resilience patterns in place and you want to validate they work under real failure conditions.
When trying to objectively benchmark delivery performance and identify what to improve first.
Before going to production with any system that holds data you cannot afford to lose.
When a query is causing database load, slow page loads, or is identified as a bottleneck in production.
When starting a new application and designing the data model β good schema design is 10x harder to fix retroactively.
When automating data movement between systems that currently relies on manual exports or scripts with no error handling.
When evaluating a NoSQL solution or designing a model for a system with known access patterns.
When data quality issues are causing downstream reports or ML models to produce wrong results.
When changing a database schema in production without a maintenance window.
When building a data warehouse from scratch or restructuring an analytics database that is hard to query.
When implementing a specific Redis pattern and wanting production-quality code with proper key design and error handling.
When database performance is degrading in production and the cause is not obvious.
When decomposing a monolith into microservices and the shared database pattern must be broken.
When building a system that must react to events in real time rather than batch processing them.
When experiencing database connection errors under load or seeing 'connection pool exhausted' errors.
When regulatory requirements, data quality issues, or organisation scale demand a formal approach to knowing what data exists and who can access it.
When building a SaaS application that serves multiple customers and must ensure strict data isolation.
When building or restructuring analytics transformations using dbt.
When database LIKE queries are too slow or too limited, and users need real search functionality.
When planning a data warehouse migration that must preserve data integrity and cannot afford significant downtime.
When exploring graph databases for a use case with complex relationships that are hard to query relationally.
When storage costs are growing, compliance requires data retention policies, or users need a right-to-erasure implementation.
When building AI features that require semantic similarity search or retrieval-augmented generation.
Before building any API endpoint β a spec agreed on before coding prevents integration rework.
When designing a GraphQL API for a data-rich domain where clients need flexible queries.
When building a platform that needs to notify external systems about events in real time.
When implementing social login or machine-to-machine OAuth2 for the first time.
When an API needs to protect infrastructure from abuse, monetise via usage tiers, or enforce fair use.
After designing or building an API that external or internal developers will consume.
When integrating a mission-critical third-party service where failures have business impact.
When an API must evolve without breaking existing integrations β which is always.
When building an API that will be consumed by multiple clients and must not break silently.
When your API is being consumed by multiple clients and you want to reduce integration friction.
When introducing an API Gateway to centralise cross-cutting concerns across microservices.
When building any state-changing API operation where duplicate requests must be safe β especially payments.
When synchronous REST is too slow or inefficient for the use case (e.g., long-running jobs, live updates).
When frontend and backend teams work in parallel and front-end needs a realistic API before the real one is built.
When you need to understand how your API is being used, who is using it, and where it is failing.
When designing internal service-to-service communication where performance, strong typing, and streaming matter.
When productising an API for external consumption and needing both technical and commercial design.
Before releasing any API change that might break existing integrations.
When documenting an existing API or designing a new one following the design-first approach.
When building a public API where inconsistent errors confuse developers and slow integrations.
At the start of any ML project β framing the problem correctly prevents months of building the wrong model.
Before training any model β feature quality determines model quality more than algorithm choice.
When starting a new ML project and needing to choose the right model family rather than defaulting to deep learning for everything.
When building an LLM-powered feature and wanting production-grade code rather than a notebook prototype.
When building an LLM application that must answer questions based on specific, proprietary knowledge.
When taking an ML model from notebook to production and needing the infrastructure to maintain it.
Before deploying any ML model β evaluation done correctly prevents shipping a model that looks good on metrics but fails in production.
When an LLM integration is producing inconsistent or low-quality outputs and the model choice is not the problem.
After deploying an ML model to production β models decay silently without monitoring.
When considering fine-tuning an LLM and wanting to evaluate whether it's justified before investing compute and time.
Before deploying any AI system that makes decisions affecting people.
When moving from a Jupyter notebook experiment to a reproducible, automated training script.
Before replacing a production model with a new version β gut feeling is not sufficient for models that affect users.
When building a supervised ML dataset from scratch and needing to maximise label quality and efficiency.
Before deploying or after encountering reliability issues in an ML system.
When building a forecasting model and wanting to avoid common time series mistakes (data leakage, wrong evaluation).
When building a personalisation feature that must work even for new users with no history.
When building an NLP feature that processes real user text and must handle domain-specific language reliably.
When AI costs are growing faster than revenue or when preparing an AI cost budget.
When preparing for ML engineering interviews.
When code reviews are inconsistent, creating friction, or not catching meaningful issues.
When preparing for technical interviews and needing a structured plan rather than random LeetCode grinding.
When writing technical documentation that must influence decisions, teach others, or be a permanent record.
When transitioning from an individual contributor to an engineering manager role.
When setting up a new machine or optimising an existing environment that feels slow or clunky.
Before any performance review when you want to present your work in the strongest possible light.
When spending time re-solving problems you've solved before because you didn't document the solution.
When wanting to break into a new technology, demonstrate skills to employers, or give back to the community.
When preparing for any compensation negotiation β preparation is the only negotiation advantage that's completely in your control.
When presenting technical work to an audience and wanting to be understood and remembered.
When building an engineering culture intentionally rather than letting it emerge by accident.
When technical debt is slowing delivery and you need budget or time to address it.
When a developer is feeling consistently overwhelmed, disengaged, or running on empty.
When onboarding a new engineer and wanting them to be productive and confident within 30 days, not 90.
Before facilitating any team retrospective where you want real insights and real actions, not performative exercises.
When preparing for a staff engineer promotion and needing to build both the impact and the evidence.
When there is more tech debt than time to fix it and you need a defensible prioritisation framework.
When building a security hardening plan for an existing application or establishing secure defaults for a new one.
Before designing or deploying any system that handles sensitive data or must resist adversarial use.
When implementing any cryptographic function β home-grown crypto is notoriously error-prone.
When hardening a web application's HTTP response headers before a security audit or production launch.
Before any security incident occurs β response plans written during an incident are too slow and too chaotic.
When building or auditing an application that handles personal data from users in regulated regions.
When designing or modernising network security for a remote or cloud-native environment.
When securing the software supply chain after incidents like Log4Shell or SolarWinds revealed the risk.
When auditing a codebase for leaked credentials or setting up prevention after a secrets leak.
When preparing for a SOC 2 audit for the first time or closing gaps from a previous audit.
When conducting security-focused code reviews or training developers to self-review for security.
After a cloud deployment or as a scheduled quarterly security review.
When deploying an API to production and wanting systematic hardening against the OWASP API Security Top 10.
When scaling security beyond a central security team to embed it in every engineering team.
When a public-facing application needs protection against availability attacks.
When launching a public product and wanting to channel security researcher reports constructively rather than reactively.
When building security visibility into a system or organisation for the first time.
When a startup needs to demonstrate security maturity to enterprise customers or investors without a large security budget.
When building or auditing any system that touches payment card data.
Before building a complex UI feature β component architecture planned upfront prevents expensive refactors.
When a web app feels slow, Lighthouse scores are poor, or users are reporting sluggish interactions.
When building a React Native feature that must work perfectly on both iOS and Android.
When building or auditing UI components that must comply with accessibility standards or reach all users.
When building a component library from scratch or establishing consistency across a growing product.
When state management is causing bugs, performance issues, or is simply growing too complex.
When mobile app performance is causing user complaints or low app store ratings.
When adding offline capability, push notifications, or home screen installation to a web application.
When building a robust frontend test suite that catches real bugs without becoming a maintenance burden.
When starting a new mobile project and needing a defensible framework choice before committing to a stack.
When adding motion to a product and wanting it to feel cohesive, professional, and fast.
When building complex forms and wanting to handle validation, async checks, and accessibility correctly from the start.
When setting up frontend deployment automation that runs quality checks before anything reaches production.
When React app performance is poor and you need systematic, targeted fixes rather than random optimisations.
When starting a mobile app and wanting a consistent, scalable architecture from day one.
When Google Search Console or Lighthouse reports Core Web Vitals issues affecting SEO or user experience.
Before submitting an app to the App Store or Play Store for the first time.
When adding multi-language support to an application or planning for it from the start.
When a mobile app handles sensitive financial, health, or authentication data and must resist device-level attacks.
When deploying a frontend application that must be observable in production.
When engineering needs a clear direction that aligns the team and informs product roadmap decisions.
When managing engineers and wanting 1:1s that are substantive, not just status updates.
When miscommunication between engineering and other functions is slowing delivery or creating frustration.
When building a formal mentorship structure or improving an informal one that isn't producing development outcomes.
When introducing or improving OKRs in an engineering organisation.
When managing a difficult situation that requires communicating bad news or delays to non-technical stakeholders.
When team structure is creating bottlenecks, unclear ownership, or slow delivery.
When making a significant architectural decision that future team members should understand without tracking down the original decision-maker.
Before any significant all-hands or large-audience engineering communication.
When scaling an engineering team and wanting consistent decision-making without centralised control.
Before any high-stakes conversation where the outcome matters and the wrong approach could damage trust.
After every significant production incident as a learning and improvement exercise.
When presenting a roadmap to multiple stakeholders with different information needs.
When feedback in the team is either absent (too polite) or destructive (too harsh) and trust is suffering.
Before acquiring, partnering with, or significantly depending on another organisation's technical capabilities.
When building a consistent, fair hiring process that produces better hiring decisions at scale.
When starting a new engineering leadership role or preparing a new leader to succeed.
Before presenting any significant engineering budget request to leadership or a board.
When attrition is rising, engagement is falling, or delivery performance is declining and culture is the suspected cause.
When being promoted to or starting a tech lead role for the first time.
Before merging any production code β especially for security-sensitive or high-traffic paths
Whenever building a public API, onboarding new engineers, or handover of a system or codebase
When a bug is non-obvious or intermittent and needs a systematic approach
Before any significant refactor, technical debt sprint, or system modernisation
When designing a new endpoint or documenting an existing one for internal or external consumption
Before starting any significant engineering work β prevents rework, aligns stakeholders, and forces clear thinking
When a query is causing performance issues, slow page loads, or high database load
When an error message is cryptic, the stack trace is long, or standard Google searches haven't resolved it