Transitioning from Rails Monolith to Microservices: Establishing Boundaries and Communication Patterns

This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.

Message originally sent by slack user U782WI24OVK

Interesting slide from a talk I was watching from Vaughn Vernon.

Step 1: Big Ball of Mud (BBoM) — Most Rails monoliths end up like this as they grow over the years mostly following The Rails Way of doing things.
Step 2: Boundaries within the monolith are established and enforced. Communication patterns between them are set in place.
Step 3: Some Components/Bounded Context have different needs in terms of scalability/deployment and so are split out to microservices. Communications patters remain the same but now use a Pub/Sub mechanism.

My company is in transition from Step 1 to 2, identifying components/bounded contexts based on domain language. Then we’d need to enforce boundaries and put communication patterns in place.

Step 3 is completely optional and not an end goal :slightly_smiling_face:

Message originally sent by slack user U7830DMKJNH

One cool thing about the bite-sized approach is you can still cheat if you miss on drawing boundaries. :grinning:

Message originally sent by slack user U782WV6188T

We’ve partially hit Step 2, where we mostly have boundaries in place, but are only just starting to enforce them. This has uncovered a huge list of work to do which will take a very long time to do, mostly because teams are busily working on new features and not really working on this technical debt :disappointed:

Message originally sent by slack user U782WI24OVK

That’s a huge achievement on its own :slightly_smiling_face:. I imagine Rails models are the hardest ones to isolate between components? Also, are you still using the tool you mentioned in your blog post (Wedge) or has it evolved into something else?

Message originally sent by slack user U782WV6188T

I imagine Rails models are the hardest ones to isolate between components?
Yeah, AR models are typically the worst offenders, and the worst to enforce boundaries around. Three patterns that we’d have to eliminate:

  1. Stop passing around AR objects, in favour of POROs or anything that can eliminate a lot of the AR surface area.
  2. Move data relevant to a completely different domain into that domain (e.g., our order model has grown with a lot of columns that aggregate information, even though they’re relevant to other domains).
  3. In places where we pass around ids instead of AR instances, some components still use the AR finder methods of the underlying class. We need to move to using some public interface to fetch the data, or refactor the code in some way so it can work without it.

Also, are you still using the tool you mentioned in your blog post (Wedge) or has it evolved into something else?
We’ve decommissioned wedge in favour of a new tool we built. We decided to go a simpler route where we people can create packages. You drop a file into a directory and it becomes a package. You can enable boundary enforcement at that point, which will prevent 1) other packages from accessing your private constants, and 2) your package accessing constants from packages you don’t depend on.

Expect to hear more about that from us in the coming months :slightly_smiling_face:

Message originally sent by slack user U7830DMKJNH

This looks like great advice! Our number 1 “rule” when we started pulling things apart was that no AR instances can ever cross a boundary :smile: