Skip to content

Slice groups

A slice group is a folder that visually groups related slices together. It is not a required part of FSD and can be optionally introduced when the number of slices grows large enough to make navigation difficult.

This document explains what a slice group is, what problem it solves, when to introduce it, and what rules to follow when applying it.

Slice groups are also referred to as structural grouping or slice grouping. In this document, we call them slice groups.

A slice group is a folder that groups related slices within the same layer.
A slice group itself is not a slice — it does not have its own segments or public API.

In other words, a slice group is a way to make the folder structure easier to find and read without changing FSD’s dependency rules.

Rule 1: A group folder is just a structural folder

A group folder does not have its own segments like model, ui, or api. It also does not have a public API like index.ts.

Rule 2: Slices inside a group are still independent

Even when slices are under the same group, the isolation rules between slices apply exactly the same as outside the group.

Rule 3: A group is only for navigation, not as a separate functional unit

Do not use a slice group as a new layer, sub-layer, or shared module.

If these rules are not followed, the group folder may end up being used as a separate structural unit rather than a simple organizational folder.
This makes it harder to distinguish which folders are actual slices and can make dependency relationships more complex.

When there are few slices, a flat structure is sufficient for navigation.
However, as slices of the same nature grow in number, you have to scan through the entire layer multiple times to find related code.

For example, suppose the entities layer has accumulated many payment-related slices.

Before grouping:

  • Directoryentities/
    • Directoryinvoice/
      • Directorymodel/
      • Directoryui/
    • Directoryreceipt/
      • Directorymodel/
      • Directoryui/
    • Directorytransaction/
      • Directorymodel/
      • Directoryui/
    • Directoryuser/
      • Directorymodel/
      • Directoryui/
    • Directoryproduct/
      • Directorymodel/
      • Directoryui/

To find the payment-related slices (invoice, receipt, transaction), you have to scan through the entire layer to locate them.

After grouping:

  • Directoryentities/
    • Directorypayment/ slice group
      • Directoryinvoice/ slice
        • Directorymodel/
        • Directoryui/
      • Directoryreceipt/ slice
        • Directorymodel/
        • Directoryui/
      • Directorytransaction/ slice
        • Directorymodel/
        • Directoryui/
    • Directoryuser/ slice (not a group)
      • Directorymodel/
      • Directoryui/
    • Directoryproduct/ slice (not a group)
      • Directorymodel/
      • Directoryui/

Now, payment-domain-related slices can be found directly under payment/.

Slice groups work this way — by placing related slices close together, they help you find related slices faster.
This is especially helpful for new team members or developers seeing the area for the first time to understand the structure.

A similar problem can appear in the pages layer.
When list, detail, create, and edit pages for a specific domain are scattered across the entire layer, discoverability suffers.

  • Directorypages/
    • DirectoryorderCreate/
      • Directoryui/
    • DirectoryorderDetail/
      • Directoryui/
    • DirectoryorderList/
      • Directoryui/
    • DirectorycustomerDetail/
      • Directoryui/
    • DirectorycustomerList/
      • Directoryui/
    • Directorysettings/
      • Directoryui/

With order-related and customer-related pages listed flat, you have to scan the entire layer to find pages for a specific domain.

Introducing slice groups allows you to see all pages of the same domain in one place.

  • Directorypages/
    • Directoryorder/ slice group
      • DirectoryorderCreate/ slice
        • Directoryui/
      • DirectoryorderDetail/ slice
        • Directoryui/
      • DirectoryorderList/ slice
        • Directoryui/
    • Directorycustomer/ slice group
      • DirectorycustomerDetail/ slice
        • Directoryui/
      • DirectorycustomerList/ slice
        • Directoryui/
    • Directorysettings/ slice (not a group)
      • Directoryui/

In this way, slice groups can be applied not only to entities but also to the pages layer when related pages grow numerous enough to make navigation difficult.

Slice groups are not a default structure — they are introduced optionally when you need to solve a navigation problem.

  • Multiple slices sharing the same business context are scattered within a layer.
    For example, invoice, receipt, and transaction all deal with the payment context but are listed flat.

  • A common parent context is naturally apparent just from the slice names.
    For example, orderCreate, orderDetail, and orderList are all understood under the common context of order.
    Similarly, invoice, receipt, and transaction can be recognized together under the payment context.

  • You find yourself repeatedly scanning the entire layer to find related slices.

  • New team members find themselves repeatedly scanning the entire layer to understand the structure.

  • Even with many slices, names alone are sufficient for quick navigation.

  • The grouping criteria feel unnatural, and different team members keep grouping things differently.

  • Even after creating a group, it only contains 1–2 slices, so the organizational benefit is minimal.

  • Creating a group actually requires additional explanation like “is this a slice or a group?”

The key point is not about increasing folder depth, but about whether the structure actually becomes easier to find and understand.

Group slices that are close from a domain model perspective.

  • Directoryentities/
    • Directorypayment/ slice group
      • Directoryinvoice/ slice
        • Directorymodel/
        • Directoryui/
      • Directoryreceipt/ slice
        • Directorymodel/
        • Directoryui/
      • Directorytransaction/ slice
        • Directorymodel/
        • Directoryui/
    • Directoryuser/ slice (not a group)
      • Directorymodel/
      • Directoryui/

Since payment/ is not a slice, it does not have its own model.ts, index.ts, or api/.

Not all slices need to be placed in a group.
Slices like user/, whose meaning is clear on its own, can remain without a group.

This can be used when multiple pages of the same domain need to be handled together.

  • Directorypages/
    • Directoryorder/ slice group
      • DirectoryorderCreate/ slice
        • Directoryui/
      • DirectoryorderDetail/ slice
        • Directoryui/
      • DirectoryorderList/ slice
        • Directoryui/
    • Directorycustomer/ slice group
      • DirectorycustomerDetail/ slice
        • Directoryui/
      • DirectorycustomerList/ slice
        • Directoryui/
    • Directorysettings/ slice (not a group)
      • Directoryui/

This structure is helpful when there are many pages on the same topic, such as list, detail, create, and edit. Opening just one parent folder lets you see all related pages together.

Yes, it can.
However, since features often span multiple entities and multiple user flows, the grouping criteria may be less clear than in entities or pages.

Therefore, it is better to view slice groups in features as an option to be used exceptionally. If there is no natural grouping criterion, it is better not to force their introduction.

A slice group should be a structural folder only.
If you start placing shared code or files that re-export multiple slices in the group folder, the group effectively starts behaving as a module.

Pattern to avoid:

  • Directoryentities/
    • Directorypayment/
      • model.ts group-level shared model
      • index.ts group-level re-export
      • Directoryinvoice/
        • Directorymodel/
        • Directoryui/
      • Directoryreceipt/
        • Directorymodel/
        • Directoryui/

In this structure, through payment/model.ts or payment/index.ts,
even though the child slices appear independent, they easily become coupled at the group level in practice.

As a result, slice boundaries become blurred, dependency directions become harder to trace, and it becomes confusing what the actual independent units are.

Correct pattern:

  • Directoryentities/
    • Directorypayment/
      • Directoryinvoice/
        • Directorymodel/
        • Directoryui/
      • Directoryreceipt/
        • Directorymodel/
        • Directoryui/

If shared logic is genuinely needed, you should first consider whether it can be separated into a more appropriate layer or a separate slice, rather than forcing it into the group folder.

Do all slices need to be placed in a group?

Section titled “Do all slices need to be placed in a group?”

No.
Only group slices that naturally belong together, and leave the rest as they are.

For example, group only cases where viewing them together is natural, like payment/invoice and payment/receipt,
while slices that are independently understood like user and settings can remain without a group.

Is it okay if the group name is included in the import path?

Section titled “Is it okay if the group name is included in the import path?”

Yes, it is fine.
For example, if the group name is included in the path like @/entities/payment/invoice, the path itself reveals which topic the slice belongs to.

However, how to expose the path is a matter of the team’s import convention.

Does having a slice group make imports between slices more flexible?

Section titled “Does having a slice group make imports between slices more flexible?”

No.
Import rules between slices are not relaxed just because they are in the same group.

A group is only a structure for navigation, and slice boundaries and dependency rules remain the same as before.