<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sam Nixon</title>
    <description>The latest articles on Forem by Sam Nixon (@sam_nixon).</description>
    <link>https://forem.com/sam_nixon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1992030%2F0de7377f-3bd5-416c-bfe6-7024aed4f887.jpg</url>
      <title>Forem: Sam Nixon</title>
      <link>https://forem.com/sam_nixon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sam_nixon"/>
    <language>en</language>
    <item>
      <title>Understanding the Backstage System Model</title>
      <dc:creator>Sam Nixon</dc:creator>
      <pubDate>Thu, 12 Dec 2024 14:21:20 +0000</pubDate>
      <link>https://forem.com/roadie/understanding-the-backstage-system-model-4cm6</link>
      <guid>https://forem.com/roadie/understanding-the-backstage-system-model-4cm6</guid>
      <description>&lt;p&gt;The &lt;a href="https://backstage.io/" rel="noopener noreferrer"&gt;Backstage Internal Developer Portal&lt;/a&gt; is, at its heart, a software catalog. As a catalog, Backstage relies on a structured System Model to represent and organize individual items, in order to make it easier to find the information development teams need. When you are setting up or running Backstage you’ll often want to tweak this Model (or make wholesale changes to it) to make it fit your organization.&lt;/p&gt;

&lt;p&gt;In this blog we’ll explore the Backstage System Model and how you can extend it if you need to.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why do we need a system model?
&lt;/h1&gt;

&lt;p&gt;Catalogs require at least some structure. If you don’t have a common taxonomy for how to describe each element inside it then it lacks coherence, like a library with no labels on the shelves (or worse yet, contradictory labels). You could pour in all of your various repositories, components, gateways, resources and clusters into a catalog and it will closely resemble a giant blob of nothing.&lt;/p&gt;

&lt;p&gt;In a Catalog, information needs to be sorted to have value. Decisions need to be made about what gets included and what does not, and you need an idea of what goes where - how things are categorized now and how they should be categorized in the future.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Basics
&lt;/h1&gt;

&lt;p&gt;The Backstage data model is made up of nodes ("entities") and edges ("relationships").&lt;/p&gt;

&lt;h2&gt;
  
  
  Entities
&lt;/h2&gt;

&lt;p&gt;The Backstage data model is built around "entities." Entities are the core units within the Backstage catalog that represent various elements of your software ecosystem. &lt;/p&gt;

&lt;p&gt;Each entity is defined via metadata (name, description, labels etc), spec (custom properties), and relations (connections with other entities). In OSS Backstage this information is often piped into Backstage via YAML files that adhere to Backstage's entity specification. Sometimes entities can also come from "Providers" which provide the entity from some source of truth (i.e. &lt;a href="https://roadie.io/docs/integrations/okta/" rel="noopener noreferrer"&gt;Users and Group entities from Okta&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This model allows teams to maintain a structured, discoverable Catalog by distributing the load across every team who owns part of the Catalog. &lt;/p&gt;

&lt;p&gt;Friction Warning: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backstage advocates for distributed ownership (i.e. each team owns the information in the Catalog that represents the software that it owns) so it can be tricky to update your model and change it over time. For example, if you wanted to replace a Kind all of the various teams would need to update their catalog files. To get around this, a lot of self-hosted Backstage users have built API-based methods for mass updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kinds
&lt;/h3&gt;

&lt;p&gt;Entities are grouped into Kinds. Kinds are like a aisle at a supermarket - everything within it is broadly cohesive and organised around similar principles.&lt;/p&gt;

&lt;p&gt;Kinds have a schema and they require a processor to correctly ingest them into the Catalog.&lt;/p&gt;

&lt;p&gt;You get some core Kinds out-of-the-box with Backstage, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;: Defines larger business domains, organizing systems and components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System&lt;/strong&gt;: Higher-level abstraction representing a collection of components working together&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt;: Represents deployable units like services, websites, or libraries)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Friction Warning: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In OSS Backstage you can extend existing Kinds or write new Kinds to include whatever you’d like, but you need to build or modify a processor each time. That means writing code.&lt;/li&gt;
&lt;li&gt;You will also need consider the long-term impact of a new Kind. You’ll likely be supporting that Kind for a long time unless you want to deprecate it and force entities that use that Kind to fail.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Types
&lt;/h3&gt;

&lt;p&gt;Kinds have Types, allowing grouping within these larger buckets.&lt;/p&gt;

&lt;p&gt;Types can be defined on-the-fly. Nothing special is needed to make Types work, any team can create a new Type just by articulating it in their catalog-info.yaml file. &lt;/p&gt;

&lt;p&gt;Friction Warning: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This can lead to a Cambrian explosion of Types, so you may want to introduce some constraint there. Validation of Types is common.&lt;/li&gt;
&lt;li&gt;Annoying errors can creep into Types (i.e.&lt;code&gt;Website&lt;/code&gt; and &lt;code&gt;Wesbite&lt;/code&gt;) unless you’re validating them in some way.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Relationships
&lt;/h2&gt;

&lt;p&gt;Relationships exist between entities to provide the connective tissue of the Backstage Catalog.&lt;/p&gt;

&lt;p&gt;Each Kind has a preset series of permissible relationships that are built when the processor runs for that Kind.&lt;/p&gt;

&lt;p&gt;For example, a simple Component might have some API relationships and dependencies defined:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```apiVersion: backstage.io/v1alpha1&lt;br&gt;
kind: Component&lt;br&gt;
metadata:&lt;br&gt;
  name: artist-web&lt;br&gt;
  description: The place to be, for great artists&lt;br&gt;
spec:&lt;br&gt;
  type: website&lt;br&gt;
  lifecycle: production&lt;br&gt;
  owner: artist-relations-team&lt;br&gt;
  system: artist-engagement-portal&lt;br&gt;
  dependsOn:&lt;br&gt;
    - resource:default/artists-db&lt;br&gt;
  dependencyOf:&lt;br&gt;
    - component:default/artist-web-lookup&lt;br&gt;
  providesApis:&lt;br&gt;
    - artist-api&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


## The Core System model

Out of the box, Backstage comes with a lot of built-in Kinds with attendant relationships so you can get started as quickly as possible. 

Some Kinds, like software templates and Locations are effectively atomic and compartmentalised away from other Kinds. The remainder are tied to how the Catalog is built and used to represented entities.

![Backstage System Model](//images.ctfassets.net/hcqpbvoqhwhm/2c89CI4rKHDNmWvCM2IHhM/37022568f4168c497956da8d9615511a/software-model-entities.drawio-3ce7f43dd236c3934209fde8f21a4d9e.svg)

They in effect represent "The Spotify Way" to model software. That’s not for everyone and won’t necessarily work perfectly for you. 

If that’s the case, you have two options:

- `Force it a little`: aka shoehorn your existing concepts into Spotify’s version. This works in a lot of cases, but is necessarily a compromise.
- `Re-model`: if that doesn’t do the trick, you need to get to work remodeling Backstage entity Kinds and types to fit your needs. Some can be done without code changes, but some need you to get your hands dirty.

# Going beyond the basics and extending the Backstage System Model

The Backstage framework is designed to be highly extensible, allowing you to modify or add new Kinds, Types, and Relationships based on the requirements of your organisation. 

That said, there are a few things you need to think about when extending the model:

### 1. No code extensibility

Backstage has flexibility baked on for a large degree of software definition. Using Types or built-in relationships handles for most situations when you want to model your software inside the Backstage System model. 80-90% of the time this will do the trick, but will often come with some degree of compromise. For example, let’s say you want to articulate `Value Streams` as a top level concept, but have to make do with `Value Streams` being a Type associated to the `Domain` Kind. It’s imperfect, but it’ll do in a pinch.

At Roadie, we evaluate and extend the System Model for our customers regularly. That works a lot of the time, but sometimes customers have niche requests that we don’t feel would benefit all our users. This is non-optimal. We want to customers the freedom to extend the model without talking to us or writing code. To achieve that we’re building a fully self-serve, no-code UI for dynamically generating Kinds and defining a system model that can be as arbitrary as you’d like: if you want a Kind called `purple-monkey-dishwasher` you should be able to have one. 

### 2. Extending the framework using code

Backstage is built around [providers](https://backstage.io/docs/features/software-catalog/external-integrations/) and [processors](https://backstage.io/docs/features/software-catalog/external-integrations/#custom-processors). Providers pull data in, processors manipulate and validate that data to build the Catalog entities and relationships. 

You can create wholly new providers to handle the ingestion of data from sources not currently handled by Backstage. The Backstage community has built  a lot of Providers over the years, but they may require tweaks to fit your specific use-case. For example, Roadie has rebuilt the GitHub provider to use webhook-based ingestion because the size of Catalog we habitually deal with break the GitHub rate limits

You can also modify processors for existing Kinds. For example to extend the list of allowed relationships between Kinds you need to tweak those processors.

You can also create wholly new processors to define new business logic or processes for manipulating and validating that data when you create a new Kind. Going back to the Value Stream example, now you can differentiate `Value Stream` from `Domain` and allow the Kinds to deviate usefully from one another. Maybe they each need different allowed relationships, or they’ll build their entities differently: the choice is yours.

### 3. Data

In the [out-of-the-box OSS Backstage model](https://backstage.io/docs/features/software-catalog/system-model/) the data for the system model comes from yaml files. This follows the GitOps model, where changes are made in git-tracked repositories and then ingested by other systems (in this case, the Backstage Catalog).

That means if you want to change or update your model you need to change all those files. That in turn means that opening PRs against every repos which contain a relevant yaml file. This is often a large undertaking, adding significant friction. That’s why most high-volume users of OSS Backstage have built API- and database-based mechanisms to do mass updates. Roadie has two: the Decorator UI and APIs to do a variety of different update patterns (idempotent updates to sync data from a source of truth into Backstage, or just pushing in whole entities via the Roadie Entities API).

# Levers to pull when extending the model

Below are some common methods for extending the Backstage data model:

### 1. **Custom Annotations**

Difficulty: Trivial

- **Why**: If you need to add metadata specific to your organization (like security labels, compliance levels, etc.), you can define custom annotations.
- **How**: Annotations are added as key-value pairs within the `metadata.annotations` field in your YAML definitions. These annotations can be used to enhance search functionality, create custom views, or provide additional context.
- **Example**: Adding `security-level: high` as an annotation for services that handle sensitive data allows you to quickly filter and prioritize compliance and monitoring for these services.

**References**:

- [Backstage Annotations Documentation](https://backstage.io/docs/features/software-catalog/well-known-annotations/#annotations): Documentation on creating custom annotations to extend metadata.



    ```yaml
    apiVersion: backstage.io/v1alpha1
    kind: Component
    metadata:
      name: fraud-detection-model
      description: "AI model for fraud detection"
      annotations:
        security-level: high

    ...
    ```



### 2. **Custom Types**

Difficulty: Easy

- **Why**: In cases where the existing entity types (Component, API, etc.) do not fit your specific resources, you can create custom entities.
- **How**: Define a new entity type in any valid catalog-info.yaml. This simple involves adding a new type to the `spec.type` in the YAML file.
- **Example**: Suppose you have machine learning models as a core resource in your project. You could define a new `model` type.

**References**:

- [Roadie Kinds and Types documentation](https://roadie.io/blog/kinds-and-types-in-backstage/) talks a lot about how to use Types without introducing problems



    ```yaml
    apiVersion: backstage.io/v1alpha1
    kind: Component
    metadata:
      name: fraud-detection-model
      description: "Machine learning model for fraud detection"
      annotations:
        security-level: high
    spec:
        type: model
      version: "1.0"
      trainingDataset: "transactions-v1"
      accuracy: "95%"
    ```



### 3. **Modifying Existing Kinds to Add Custom Relations**

Difficulty: Normal

- **Why**: Relationships between entities help you capture dependencies, ownership, and team structures within your catalog. If your use case involves additional relationship types, custom relations can improve representation.
- **How**: Modify the relevant processor for a given Kind to enable new types of relationships to be built for that kind. Then define relations within the `spec.relations` section of the YAML file.
- **Example**: Suppose you want to track models associated with data sources. You could create a custom relation `usesDataFrom`, linking ML models to the Resource entities that document data sources they rely on.

**References**:

- [Roadie Kinds and Types Documentation](https://roadie.io/blog/kinds-and-types-in-backstage/): Provides practical examples of defining and extending Kinds.



```yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: fraud-detection-model
  description: "Machine learning model for fraud detection"
  annotations:
    security-level: high
spec:
    type: model
  version: "1.0"
  trainingDataset: "transactions-v1"
  accuracy: "95%"
  relations:
  - type: usesDataFrom
    targetRef: resource:exampleorg/some-data-source
    target:
      kind: resource
      namespace: exampleorg
      name: some-data-source
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;strong&gt;Creating Entirely New Custom Kinds&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Difficulty: Normal / Hard&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt;: When the System Model cannot adequately encapsulate how you build software or the relationships between various parts of your organisation, you will need to build a custom Kind.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How&lt;/strong&gt;: Write a new processor for that Kind and define a custom schema for that Kind.  This ensures all entities adhere to required fields, valid types, and constraints, providing an additional layer of validation. Then add new catalog-info.yaml files for the new Kind to relevant resources, or modify existing catalog-info.yaml files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: For the &lt;code&gt;MLModel&lt;/code&gt; entity, you could create a new Kind to represent that in your System model. Using that new Kind you could then model relationships  as &lt;code&gt;version&lt;/code&gt;, &lt;code&gt;trainingDate&lt;/code&gt;, and &lt;code&gt;accuracy&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://backstage.io/docs/features/software-catalog/descriptor-format/" rel="noopener noreferrer"&gt;Backstage JSON Schema Documentation&lt;/a&gt;: Explains how to define and enforce custom schemas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Backstage is an extremely flexible framework for modelling software and once the building blocks and options are understood it’s simple enough to fully customise the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful links:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://backstage.io/docs/features/software-catalog/system-model" rel="noopener noreferrer"&gt;Backstage System Model&lt;/a&gt;: official docs and a good starter diagram for how entities in the Catalog interact.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://backstage.io/docs/features/software-catalog/life-of-an-entity" rel="noopener noreferrer"&gt;Backstage Entities&lt;/a&gt;: official docs on the lifecycle of entities&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://backstage.io/docs/features/software-catalog/well-known-relations" rel="noopener noreferrer"&gt;Backstage Relationships&lt;/a&gt;: official docs on how relationships work inside Backstage&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://roadie.io/blog/modelling-software-backstage/" rel="noopener noreferrer"&gt;Modelling software in Backstage&lt;/a&gt;: Roadie blog from 2021 about how to model software in Backstage using the core system model. This still represents a great primer on the out-of-the-box system model and how you could use it.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>backstage</category>
      <category>platformengineering</category>
    </item>
    <item>
      <title>How to Define Engineering Standards (with Backstage)</title>
      <dc:creator>Sam Nixon</dc:creator>
      <pubDate>Sat, 28 Sep 2024 16:12:11 +0000</pubDate>
      <link>https://forem.com/sam_nixon/how-to-define-engineering-standards-with-backstage-5eng</link>
      <guid>https://forem.com/sam_nixon/how-to-define-engineering-standards-with-backstage-5eng</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;At Roadie we don’t claim to be experts in writing software standards - we’re done it ourselves, both for Roadie and before as part of other startups, scaleups and large companies, but we don’t claim to be world-beaters at it. What we can claim is that we’ve seen many, many companies go through the journey to create standards and then apply them and we have seen what works. &lt;/p&gt;

&lt;p&gt;This post originally appeared on the Roadie blog over at &lt;a href="https://roadie.io/blog/how-to-define-engineering-standards/" rel="noopener noreferrer"&gt;https://roadie.io/blog/how-to-define-engineering-standards/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why standardise?
&lt;/h2&gt;

&lt;p&gt;Defining and adopting engineering standards is essential for organizations as they scale. &lt;/p&gt;

&lt;p&gt;Teams involved in Platform initiatives normally find themselves as the first intrepid explorers in this territory for larger organizations.&lt;/p&gt;

&lt;p&gt;Building tooling for multiple different teams and departments requires consistency and a coherent set of practices. Only then can teams coordinate, share and build scalable, maintainable, and secure software together.&lt;/p&gt;

&lt;p&gt;Without standardization, answering basic questions becomes impossible and progress is painfully slow, a problem that often hits home at times of peak stress. How can you know which teams operate publicly facing software that has critical vulnerabilities if only half of the teams are using a dependency scanning tool? How can you roll out a new security requirement when engineering teams are each using one of 5 different security tools?&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Engineering Standards
&lt;/h2&gt;

&lt;p&gt;Engineering standards are formal guidelines that outline how code should be written, how systems should be designed, and how processes should be executed. These standards ensure that all engineers are working toward the same quality benchmarks.&lt;/p&gt;

&lt;p&gt;That means you need consensus between teams about what exactly should be in those standards. In order to do that, even before you decide what the standards are that you’d like to focus on, it’s good to have a plan for how you can agree together on what they should be.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategies for Agreeing on Engineering Standards
&lt;/h3&gt;

&lt;p&gt;Getting a team to agree on a set of engineering standards can be challenging but is crucial for their success. Here are some strategies to help facilitate agreement:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with your own &lt;a href="https://aws.amazon.com/what-is/sdlc/" rel="noopener noreferrer"&gt;SDLC&lt;/a&gt; - if you have one - and/or Industry Best Practices:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Software Development Lifecycle and Production Readiness documents often effectively contain a lot of standards recommendations. They’re extremely useful as an input into a formal set of software standards and the two should be synced closely together.&lt;/li&gt;
&lt;li&gt;Use industry standards like &lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP for security&lt;/a&gt; or &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/" rel="noopener noreferrer"&gt;WCAG&lt;/a&gt; for accessibility as a baseline. This helps reduce subjective debate by relying on well-known benchmarks. For example, it’s hard to argue that secure logging isn’t important when it shows up prominently in the &lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP table&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborate across teams and functions:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Involve engineers, product managers, and operations teams in defining the standards.&lt;/li&gt;
&lt;li&gt;Run workshops where everyone can voice their opinions, then converge on a decision.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Appoint a champion:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;Usually this is a member of engineering leadership who is responsible for driving this process and the eventual rollout. &lt;/li&gt;
&lt;li&gt;Occasionally this can be a group though, like &lt;a href="https://github.com/jakubnabrdalik/architecture-guild" rel="noopener noreferrer"&gt;an Architecture guild&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Gradually implement:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Start small, either:

&lt;ul&gt;
&lt;li&gt;A minimal set of standards and build from there as the team gets more comfortable. For example, you can start by enforcing code formatting standards and then gradually add performance or security checks.&lt;/li&gt;
&lt;li&gt;A full set of standards with only a few initial checks so that the team can get comfortable with the whole suite of standards&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;These strategies allow teams to give feedback and for the standards to evolve before they are fully enforced&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Regularly review and update:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;An engineering standards document should never stand still.&lt;/li&gt;
&lt;li&gt;Once the standards are set, encoded them into your systems.&lt;/li&gt;
&lt;li&gt;Hold regular reviews (e.g., fortnightly or monthly) to review progress of each team&lt;/li&gt;
&lt;li&gt;Create a regular cadence of review for the standards themselves, based on team feedback and new technology trends and recommit. Once a year is often enough here.&lt;/li&gt;
&lt;li&gt;As part of these reviews, use data to demonstrate the value of each standard (e.g., reduced production errors, improved system uptime).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h3&gt;
  
  
  Common Standards
&lt;/h3&gt;

&lt;p&gt;To make this concept concrete, let’s consider some common standards teams might define (nb: this is by definition a non-exhaustive list):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Logging and Monitoring:&lt;/strong&gt; Log levels, message formats, error tracking, use of a centralized tool, use of alerts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Authentication, authorization, encryption, secure coding practices, and dependency vulnerability management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Response times, load management, and scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; Redundancy strategies, failure handling, backup and recovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Quality:&lt;/strong&gt; Style guides, review processes, formatting rules, and readability standards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; API documentation, code comments, and README files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing:&lt;/strong&gt; Code coverage, test automation, and test environment standards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control:&lt;/strong&gt; Branching strategies, commit message guidelines, and pull request processes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Continuous Integration/Continuous Deployment (CI/CD) pipelines, rollback procedures, and environment configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: &lt;a href="https://www.w3.org/TR/WCAG22/" rel="noopener noreferrer"&gt;WCAG 2.2&lt;/a&gt; guidelines, color contrast, text-to-speech, keyboard navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't want to over-elaborate at this point. It is important to end up with ~8-10 different areas to focus on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nice vocabulary to use when setting standards
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Must&lt;/code&gt;. Used to define mandatory items. i.e. &lt;code&gt;A service must use a logger&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Should&lt;/code&gt;. Used to define items which are reasonably expected to exist. If a services choses not to adopt this standard, the expectation is that they justify why not.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;May /&lt;/code&gt; &lt;code&gt;Could / Will&lt;/code&gt;. Used to define items which are more aspirational or for services that are consider mature.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An example: AcmeCorp.com
&lt;/h2&gt;

&lt;p&gt;Let’s imaginee &lt;strong&gt;&lt;em&gt;AcmeCorp.com&lt;/em&gt;&lt;/strong&gt; are a well-known platform selling books, clothes, food, laptops, paddling pools and power tools around the world. They’re an anything store, if you will. &lt;/p&gt;

&lt;p&gt;Availability and reliability are key to their business, so they spend a lot of time thinking about how to measure and improve that for the software they build.&lt;/p&gt;

&lt;p&gt;Previously, teams would simply assert that their service was reliable, performance, secure etc, but aside from anecdotally looking at the past weeks/months/years to validate that assertion, it was hard to prove or disprove. It was also hard to compare across services.&lt;/p&gt;

&lt;p&gt;To help that, a cross-functional group at &lt;strong&gt;AcmeCorp.com&lt;/strong&gt; have agreed a series of standards that they believe will ensure their service stand up to considerable load during peak periods, and that if outages or incidents do happen that they’ll recover quickly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Standard&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monitoring&lt;/td&gt;
&lt;td&gt;Health checks for critical components must be defined and an ideal state determined.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Service state must be constantly observed and recorded and dashboards should be created to show this data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Monitoring should have metrics that describe how effective a service is. These metrics are available and easily viewable on a dashboard.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Events should be exported and/or sampled and collected in addition to other metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Availability&lt;/td&gt;
&lt;td&gt;Service availability must be determined programmatically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Expected and unexpected behavior for a given service must be defined in tests and alerts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Basic SLIs should be defined and used to calculate SLO targets. This should include the number of number of good events / total number of events are being recorded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;SLOs should be actively measured, calculated, and displayed in a dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Error budgets may established and a policy outlining what to do when service runs out of budget is established.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;SLOs (and error budget policy where appropriate) should be documented in a prominent location where teams and stakeholders can easily review.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logging&lt;/td&gt;
&lt;td&gt;Logs must show startup, shutdown, and errors.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Logs must have have a rotation and retention policy defined.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Logs from all hosts must be sent to a centralized location.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Logging pipeline must be resilient to transient failures and should be fully recoverable when ingestion returns to a healthy state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alerting&lt;/td&gt;
&lt;td&gt;Basic health checks must be attached to alerts when failing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;A dashboard must display all alerts currently firing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;The body of any alert must contain information that is be needed to diagnose and fix the problem.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;An official on-call rotation for high-priority alerts must be configured and activated.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;High-priority alerts should tuned such that they don't fire outside of business hours unless necessary. If resolution of an issue can wait until business hours, it should not page the on- call engineer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;High-priority alerts should be triggered only for urgent, actionable issues that require a human's intervention.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Operating manuals for service scaling must be up to date and consumable by newly onboarded or tangentially-familiar engineers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Service must handle unexpected increases in load without manual effort, up to a known threshold.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Unexpected increases and decreases in load must be handled automatically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Unexpected increases in load above a known threshold may be handled automatically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Owners of a service may run regular scaling exercises to test scaling assumptions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Service may be able to deprioritize features and load when needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resiliency and Recovery&lt;/td&gt;
&lt;td&gt;Run books must exist that outlines steps of recovering from loss of capacity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Owners should have conducted testing on outages to validate recovery run books and quantify performance degradation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Owners should demonstrate manual recovery is possible with minimal performance degradation (within established threshold)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Owners may demonstrate automatically recovery is possible with minimal performance degradation (within established threshold)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Breaking Standards Down Into Scorecards and Checks
&lt;/h2&gt;

&lt;p&gt;Once the standards are defined, they need to be actionable, measurable, and concisely group so that teams can understand them. This is where checks and scorecards come into play.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scorecards
&lt;/h3&gt;

&lt;p&gt;Scorecards allow teams to measure in only a few data points how well they are adhering to their engineering standards across a project or organization. &lt;/p&gt;

&lt;p&gt;Scorecards should flow naturally from your standards and be fairly simple to define. Name them things that align with those standards and are comprehensible as a bucket of actionable checks against those standards.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Security&lt;/code&gt; is a good, simple, easy to understand name. If you wanted to create levels for your scorecards to have some sense of progression, you could say &lt;code&gt;Security - Level 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Secure Coding Standards&lt;/code&gt; might be a good option if you wanted to go to a more granular level with your scorecards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try and end up with ~10.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checks
&lt;/h3&gt;

&lt;p&gt;For each scorecard/standard, you need to break it down into one or more specific checks. A "check" is a verifiable condition that can be automated or manually enforced.&lt;/p&gt;

&lt;p&gt;Just like Scorecards, Checks should be named things that are comprehensible but crucially should also be actionable. &lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Node version should be &amp;gt;18&lt;/code&gt; is a clear true/false statement about what the expectation is for a given service that uses Node.js. It is also clear what needs to be done in order to pass that check.&lt;/li&gt;
&lt;li&gt;Similarly &lt;code&gt;CODEOWNERS should be enabled&lt;/code&gt; draws an even more direct line to what needs to be done for a given service to pass a check.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At Roadie we use our Tech Insights plugin to build these checks - the backend for which we also &lt;a href="https://roadie.io/backstage/plugins/tech-insights/" rel="noopener noreferrer"&gt;open sourced&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Whether you’re using Roadie, OSS or hand-rolling these checks, it’s important to have an idea of what a computationally enforceable check would look like for each of your standards.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automating and visualising standards
&lt;/h3&gt;

&lt;p&gt;Last but not least, you need some way to repeatedly check standards are being adhered to.&lt;/p&gt;

&lt;p&gt;This usually comes in two forms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can programatically check to see whether documentation exists. This is often in the form of a runbook at a given path, i.e. &lt;code&gt;/docs/runbooks/recovery&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A third party tool is used to capture data that can then be interrogated programmatically. For example, this can be something as simple as an SLO existing in Datadog for a given service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both data sources can be used to confirm at scale whether or not a given service is correctly adhering to a given standard.  &lt;/p&gt;

&lt;p&gt;Teams no longer have to assert compliance, they simply need to ensure that the evidence is currently surfaced to prove that they comply.&lt;/p&gt;

&lt;p&gt;Many scorecarding solutions do exactly this for you, without the need for teams to individual wire up different systems. For example, Roadie customers use &lt;a href="https://roadie.io/docs/tech-insights/introduction/" rel="noopener noreferrer"&gt;Tech Insights plugin&lt;/a&gt; to provide standardised, automated checks across their entire software catalog with minimal or no intervention from individual teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Returning to AcmeCorp
&lt;/h3&gt;

&lt;p&gt;Using the example of AcmeCorp.com again, let’s take one of their areas are turn it into a Scorecard with a series of checks. They use &lt;a href="https://www.datadoghq.com/" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt; for their dashboards and &lt;a href="https://sentry.io/welcome/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt; for their logging so they can both provide sources of truth for their checks.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scorecard&lt;/th&gt;
&lt;th&gt;Underlying Standard&lt;/th&gt;
&lt;th&gt;Checks&lt;/th&gt;
&lt;th&gt;Data source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monitoring&lt;/td&gt;
&lt;td&gt;Health checks for critical components must be defined and an ideal state determined.&lt;/td&gt;
&lt;td&gt;Service has &amp;gt;1 health checks defined&lt;/td&gt;
&lt;td&gt;Repo file that contains healthcheck test results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Health checks for critical components must be defined and an ideal state determined.&lt;/td&gt;
&lt;td&gt;Healthcheck test results return current status codes&lt;/td&gt;
&lt;td&gt;Repo file that contains healthcheck test results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Service state must be constantly observed and recorded and dashboards should be created to show this data.&lt;/td&gt;
&lt;td&gt;Service has a Datadog dashboard to record service health&lt;/td&gt;
&lt;td&gt;Datadog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Monitoring should have metrics that describe how effective a service is. These metrics are available and easily viewable on a dashboard.&lt;/td&gt;
&lt;td&gt;&amp;gt;1 service metric is defined in Datadog&lt;/td&gt;
&lt;td&gt;Datadog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Monitoring should have metrics that describe how effective a service is. These metrics are available and easily viewable on a dashboard.&lt;/td&gt;
&lt;td&gt;Datadog metric monitor is configured&lt;/td&gt;
&lt;td&gt;Datadog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Events should be exported and/or sampled and collected in addition to other metrics&lt;/td&gt;
&lt;td&gt;&amp;gt;1 event has been sent to Sentry in the last day&lt;/td&gt;
&lt;td&gt;Sentry&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Making a fix easy to implement
&lt;/h3&gt;

&lt;p&gt;The final stage of implementing engineering standards is to make adherence as simple and easy as possible. If a check or scorecard failure is hard to achieve then teams will take longer to resolve it, the rate at which they resolve it will be lower, and standards will ultimately suffer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ask yourself:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;How many steps does it take to bring a service into compliance for a given standard? How can that be reduced?&lt;/li&gt;
&lt;li&gt;How can common or shared systems be leverage to help multiple teams into compliance? Using the AcmeCorp example above, a &lt;a href="https://app.datadoghq.com/dashboard/lists" rel="noopener noreferrer"&gt;templated Dashboard for Datadog&lt;/a&gt; could help all teams skip design and production steps when setting up a Monitoring dashboard.&lt;/li&gt;
&lt;li&gt;How can the overall cycle time from error to resolution be reduced? Can common fixes be added to shared repositories or How To guides be written to help teams?&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Where possible, implement quick fix options
&lt;/h4&gt;

&lt;p&gt;At Roadie we use the Backstage scaffolder to automate many of the fixes for our scorecards. To take a simple example, one of our engineering standards is that branch protection must be enabled on any repository we create. If a service is linked to a repository without branch protection it fails that check. To resolve it, we have a 3-second Scaffolder template that can modify the GitHub settings associated with the repository. The only thing the team needs to do is look at the check and click a button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Defining engineering standards is critical for ensuring that software systems are built and maintained with quality, security, and scalability in mind. Breaking these standards down into checks and scorecards allows teams to monitor compliance and ensure continuous improvement. By following a collaborative approach to defining standards and making them measurable, teams can streamline their development processes and produce more reliable software.&lt;/p&gt;

&lt;p&gt;Whatever you are focusing on, the key to success lies in making standards actionable, measurable, and adaptable.&lt;/p&gt;

</description>
      <category>sre</category>
      <category>backstage</category>
    </item>
  </channel>
</rss>
