Greg Park


Building new features with horizontal or vertical slices

December 08, 2023

Imagine that you just learned that you’ll need to build a new feature: custom profile pages for users.

The UX and product teams provided a high fidelity mockup of the desired UI:

A screenshot of a Tailwind UI form component
An example of the new profile page you'll need to build. (Pssst, this is actually just a screenshot of one of the UI components available from Tailwind UI.).

It’s a big feature, so you’ll need to slices it into smaller pieces first. But what are the right slices?

This is the art of story slicing. The size and nature of your slices can mean the difference between a smooth, consistent rollout of valuable work and hot mess.

Consider two types of slices: horizontal and vertical.

Horizontal Slicing

This new feature will touch several architectural layers of the application:

An example of architectural layers involved in the new feature
The new profile feature will require changes to every layer of the application architecture.

A horizontal slicing approach breaks down the work according to the architectural layers, such that each slice of work is only concerned with a single layer.

An example of horizontal slices, based on architectural layers
Horizontal slices break down the work along architectural layers.

My bet is that horizontal slices are intuitive from a developer’s point of view. Developers are naturally aware of the architectural layers and the nature of the work required by each layers. In my experience, most developers will default to slicing work horizontally and sticking to one layer at a time.

For example, the first slice might make all of the database-related changes. The second slice adds application logic. The third slice builds the JSON API layer, and so on. After all slices are shipped, the feature is complete and ready for users!

Examples of horizontal slices

Each of these horizontal slices is limited to a single architectural layer.

Advantages of horizontal slices

Limits focus on a single layer at a time 👍

Horizontal slices require less context switching, or jumping between different types of changes (database vs. application code vs. UI) in the same slice.

It also lets developers with specialized skillsets use their strengths, e.g., the team’s “frontend specialist” can focus on the UI layer.

Enables potential parallelization 👍

If the interactions between the layers are very clear and well-understood, it’s possible to parallelize horizontal slices. For example, one pair tackles the database changes, while another pair writes the backend logic, and another works on the frontend UI, so that all horizontal slices are completed simultaneously.

Drawbacks of horizontal slices

Delays risk discovery 👎

Horizontal slicing assumes that team really does understand how all of the layers will fit together. Ideally, when the database changes and the application code changes are complete, they will “just work”.

But, if the team is wrong and the slices don’t “just work” together, they won’t discover this until very late in the project, leading to unplanned “rework” and “bug fix” changes after the planned horizontal slices are shipped.

Example: When we were finally about to ship the UI piece, we realized that we actually needed a different database schema to support a critical part of the UI. Now we’re blocked by the database change, but that also means we’ll need to update the application code too. So we’ve added on another database slice and an application slice before we can finish the UI.

Reinforces knowledge/skill silos 👎

If teammates only pick up changes that fit their existing strengths, the rest of the team may miss out on an opportunity to build new skills.

Example: Most projects have some database slices, application slices, and UI slices. Pat always does the database cards, Charlie always writes the application code, and Sam sticks to the UI parts. Everyone tends to stay in their favorite areas and avoids learning about new things.

Requires more communication overhead 👎

If horizontal slices are parallelized, developers working on different slices must frequently communicate to keep the layers “in sync” during development.

Example: We’ve distributed the slices across several dev pairs, but let’s check in daily to make sure that the database changes matches the app changes and the API spec.

Delivers less incremental value per slice 👎

In the example feature above, the end user doesn’t receive any value until every horizontal slice is complete. From the perspective of the user, the feature is non-existent until the completion of all of the dev work. The user is unable to use any part of the feature and can’t provide any feedback.

Example: We put a lot of work in this sprint to complete the database schema needed to support user profiles. Nobody outside of the dev team cares about the database schema, so there’s nothing to demo today. But we swear it’s important!

Vertical Slicing

A vertical slicing approach breaks down the work by functionality or value (to the user).

An example of vertical slices, based on useable features rather than architectural layers
Vertical slices break down the work along useable pieces of functionality rather than architectural layers.

Vertical slices often combine multiple architectural layers, if that’s necessary to deliver a meaningful piece of functionality. Development work is limited to just what is needed to deliver the functionality.

With each completed vertical slice, something useable/valuable should be delivered to the end user.

Vertical slicing is more intuitive to a customer or end user – the slices align with functionality that the user needs, not the technical layers behind it.

Examples of vertical slices

Each of these vertical slices delivers something useful to the end user, but every slice could require small, coordinated changes at every layer: database, application, API, and UI.

Advantages of vertical slices

Uncovers risk earlier 👍

The first vertical slice requires the developers to integrate multiple layers. If there’s a bad assumption about how the layers would fit together, it will uncovered very early.

Also, because vertical slices can get demo-able features in front of users and stakeholders earlier, they also uncover bad assumptions about how the feature should work or look.

Delivers value incrementally 👍

The end user (and product owners) can see tangible improvements in functionality with every vertical slice, rather than waiting for every horizontal slice to be completed. They can also give feedback earlier, because features are useable (or at least demo-able) earlier.

Requires broad skillsets for every slice 👍

Developers need to work across multiple layers to complete every slice. A developer who prefers working on frontend UI might need to work on the database layer. This might not play to their strengths, but it gives them valuable exposure to different parts of the system and builds a broader skillset.

Prioritizes functionality and value to the user 👍

Defining a vertical slices forces the dev team to frame their work in terms of the value it delivers — using the language that stakeholders and users care about — rather than technical jargon.

Drawbacks of vertical slices

Higher slice complexity 👎

Vertical slices combine multiple layers, so even small pieces of functionality can feel complex. Vertical slices often need to be very “thin” (adding very small increments of functionality) to avoid becoming overwhelming.

Example: A single vertical slice could require pull requests for multiple layers: database, application backend, and application front-end. To make this manageable, we’ll focus on a small portion of the user profile. That way the database change involves a single table, the application change is two functions, and the UI layers is a single component.

Difficult to parallelize 👎

Different vertical slices often touch similar areas across multiple layers, making it harder to parallelize vertical slices without lot of conflicts.

Example: If we try to parallelize the vertical slices of the profile feature, the pairs will constantly be touching the same database tables and modules. Ultimately, it’s smoother to deliver each slice sequentially.

What’s better, horizontal or vertical slices?

Vertical slices require more upfront thinking and planning. But they’ll help you discover risk earlier, deliver value consistently, and get feedback sooner.

Horizontal slices are intuitive to the dev team and feel faster to complete. But they delay risk, delay delivery, and require more communication overhead.

I think there’s a strong case for trying to slice as vertically as possible first, but be aware that this requires more work upfront.

Sometimes horizontal slices are unavoidable.

Consider work like refactoring and framework upgrades. They may be valuable in a way that a user doesn’t care about (e.g., maintenance, security, or performance), but doesn’t mean we shouldn’t do them.

Look hard for thin vertical slices

I think developers sometimes avoid vertical slices because they feel “too big”, and we are naturally averse to large changes.

Finding a reasonably thin vertical slice sometimes required some creativity. If you search for articles on “story splitting,” you’ll find plenty of lists of dimensions on which you could try slicing.

The big idea is that size is slice size is proportional to complexity. So,

Examples: