Here's how we run retrospectives across a ~500 person R&D org at GitLab :

  1. We host retrospectives once a month following each release. In the 13.2 release, we released a lot!
  2. Each team hosts their own retrospective covering what went well, what went wrong, and how we can improve. We track team-wide progress in an issue:
  3. Each team contributes their learnings into a summary and discussion document:
  4. We pre-record a summary of highlights to watch async:
  5. We pick two topics for a live discussion and livestream it:
  6. We gather feedback on the retrospective and improve for the next one:
  7. We document our process in our handbook:


Here's how we estimate work on GitLab's Growth Engineering team:
• We use a Fibonacci scale of 1, 2, 3, 5, 8, 13.
• 1 is the simplest possible change.
• 13 is a significant change with many unknowns.
• We estimate high if we can't decide on the weight of an issue.
• If an issue has many unknowns, we break it into separate spike and implementation issues.
• Anything over 5 can likely be broken down into a smaller iterations.
• Estimates provide us with a baseline level of predictability.
• We optimize for velocity rather than predictability. We aim for 70% predictability.
• Estimates can be adjusted and revised any time.

More details here:


Here's how we prioritize work on GitLab's R&D teams:
• Security, Data-loss, and Availability issues come above all feature work.
• SLAs/SLOs are set based on Severity / Priority (S/P).
• S1/P1s are resolved in a few hours.
• S4/P4s are resolved in 1-2 milestones.
• Next are Regressions, Customer Commitments, Availability and Performance Optimizations
• After that are Analytics, UX Improvements, ARR Drivers, Dogfooding, Features / Tech Debt.
• To address Tech Debt, some teams carve out 20% of each milestone to pay off debt.
• To prioritize Features, we recommend using the RICE framework to score based on Reach, Impact, Confidence, Effort.

More details here:


Conway's Law

Organizations design systems that mirror their own communication structure.
Source: Wikipedia

Boring Solutions and Progressive Enhancement

Similar to iteration, you improve things as needed. You likely don't need VueJS/ReactJS right from the start. You also probably don't need Kubernetes right from the start. Start with boring solutions and only add complexity as needed.

Preferred Techstack

There are many different directions you can go with a techstack. My preference when choosing technologies is to:
- Simple Boring Solutions: Simple solutions allow you to move quickly. Boring solutions means you focus on using proven technologies rather than something shiny and new that's un-tested.
- Quick Iterations: Iteration speed always wins. Building quickly gives you a path towards better functionality. If you take on too much complexity at the beginning you'll never get started.
- Progressive Enhancement: Start with simple technologies and swap out certain components as it requires more functionality. You can get very far with progressive enhancement. Eventually a tipping point may be reached where it's inefficient to continue work with the simple technology and it makes more sense to fully make the transition to a more complex technology -- make this jump later when needed, not from the start. A good example of this is to never start with micro-services -- always start with a monolith then slowly break out services as needed.

What this means in practice is:
- Keeping your codebase simple so that a single engineer can fully understand it.
- Aiming for a single codebase that works across all platforms (web, ios, android).
- Standardized design system for a uniform UX and efficient design process.

Category Stack
Infra Digital Ocean, Ubuntu, Nginx
Web Backend Rails, Postgres, Redis, Sidekiq
Web Frontend HAML, Boostrap, JQuery, Hotwire, Turbo, Stimulus, ViewComponent (when needed)
Web Frontend Heavy Client-side Interaction VueJS, Webpack
iOS Client Swift, Turbo
Android Client Kotlin, Turbo

Techstack Comparison

- Rails + jQuery Rails + Hotwire Rails + VueJS Rails + ReactJS RailsAPI + NodeJS / VueJS + Ionic / Capacitor RailsAPI + NextJS / ReactJS + Ionic / Capacitor Rails API + NodeJS / ReactJS + ReactNative
Backend Rails Rails Rails Rails Rails API Rails API Rails API
Web Frontend Rails, jQuery Rails, jQuery, Hotwire / Turbo / Stimulus Rails, VueJS Rails, ReactJS NuxtJS / VueJS NextJS / ReactJS NextJS / ReactJS
Mobile Frontend Cordova Strada / Hotwire / Turbo / Stimulus Cordova Cordova Ionic / Capacitor Ionic / Capacitor ReactNative
Number of codebases One + Mobile Wrappers One + Mobile Wrappers One + Mobile Wrappers One + Mobile Wrappers Two + Mobile Wrappers Two + Mobile Wrappers Three
Native or Hybrid Hybrid Hybrid Hybrid Hybrid Hybrid Hybrid Native
SEO Friendly (SSR) Yes Yes Yes using Webpacker Yes using Webpacker Yes using NuxtJS Yes using NextJS Yes using NextJS
Community Support 7 5 6 7 6 7 8
Simplicity 8 7 5 5 4 4 3
UX 4 6 7 7 7 7 8
Performance 4 6 7 7 7 7 8
Notes Able to incrementally swap VueJS/ReactJS components in when needed Able to incrementally swap VueJS/ReactJS components in when needed

Editable source

- Vue.js And SEO: How To Optimize Reactive Websites For Search Engines And Bots
- Developing mobile applications with apache cordova
- Quora: Which hybrid Framework has more future Ionic React or Meteor
- RailsConf 2016 - Turbolinks 5: I Can’t Believe It’s Not Native! by Sam Stephenson
- Hacker News readers as Progressive Web Apps

Impacts of AI

In a world with AI pair programmers, memorizing programming syntax isn't important. Instead, focus on understanding the complexities of software that AI doesn't understand yet, such as system architecture.