diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/PreMixinIndex.java b/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/PreMixinIndex.java
new file mode 100644
index 00000000000..d6d64ae7b6a
--- /dev/null
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/knowledge/PreMixinIndex.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ *  http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.smithy.model.knowledge;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import software.amazon.smithy.model.Model;
+import software.amazon.smithy.model.shapes.ListShape;
+import software.amazon.smithy.model.shapes.MapShape;
+import software.amazon.smithy.model.shapes.MemberShape;
+import software.amazon.smithy.model.shapes.OperationShape;
+import software.amazon.smithy.model.shapes.ServiceShape;
+import software.amazon.smithy.model.shapes.SetShape;
+import software.amazon.smithy.model.shapes.Shape;
+import software.amazon.smithy.model.shapes.ShapeId;
+import software.amazon.smithy.model.shapes.ShapeVisitor;
+import software.amazon.smithy.model.shapes.StructureShape;
+import software.amazon.smithy.model.shapes.UnionShape;
+
+/**
+ * Index of shapes stripped down to only their introduced properties.
+ *
+ * <p>This is primarily useful in serialization to determine what
+ * properties to actually serialize vs what is computed as part of
+ * mixins.
+ */
+public final class PreMixinIndex implements KnowledgeIndex {
+
+    private final Map<ShapeId, Shape> preMixinShapes = new HashMap<>();
+
+    public PreMixinIndex(Model model) {
+        MixinUnroller unroller = new MixinUnroller(model);
+        model.shapes()
+            .filter(shape -> !shape.isMemberShape())
+            .forEach(shape -> {
+                if (!shape.getMixins().isEmpty()) {
+                    preMixinShapes.put(shape.getId(), shape.accept(unroller));
+                }
+            });
+    }
+
+    public static PreMixinIndex of(Model model) {
+        return model.getKnowledge(PreMixinIndex.class, PreMixinIndex::new);
+    }
+
+    /**
+     * Gets a version of the shape that has mixin properties stripped out.
+     *
+     * <p>NOTE: mixin members with introduced traits WILL be present in
+     * their entirety. The only way to determine if those members originally
+     * were defined in a mixin is to have an original copy of the shape to
+     * compare against. Any members of the shape that themselves have mixins
+     * are inherited.
+     *
+     * @param shape The shape to strip mixin data from.
+     * @return A version of the shape without mixin data.
+     */
+    public Shape getPreMixinShape(Shape shape) {
+        return preMixinShapes.getOrDefault(shape.getId(), shape);
+    }
+
+    private static final class MixinUnroller extends ShapeVisitor.Default<Shape> {
+
+        private final Model model;
+
+        private MixinUnroller(Model model) {
+            this.model = model;
+        }
+
+        @Override
+        protected Shape getDefault(Shape shape) {
+            return Shape.shapeToBuilder(shape)
+                    .clearMixins()
+                    .traits(shape.getIntroducedTraits().values())
+                    .build();
+        }
+
+        @Override
+        public Shape listShape(ListShape shape) {
+            return shape.toBuilder()
+                    .clearMixins()
+                    .traits(shape.getIntroducedTraits().values())
+                    .member((MemberShape) shape.getMember().accept(this))
+                    .build();
+        }
+
+        @Override
+        public Shape setShape(SetShape shape) {
+            return shape.toBuilder()
+                    .clearMixins()
+                    .traits(shape.getIntroducedTraits().values())
+                    .member((MemberShape) shape.getMember().accept(this))
+                    .build();
+        }
+
+        @Override
+        public Shape mapShape(MapShape shape) {
+            return shape.toBuilder()
+                    .clearMixins()
+                    .traits(shape.getIntroducedTraits().values())
+                    .key((MemberShape) shape.getKey().accept(this))
+                    .value((MemberShape) shape.getValue().accept(this))
+                    .build();
+        }
+
+        @Override
+        public Shape structureShape(StructureShape shape) {
+            StructureShape.Builder builder = shape.toBuilder()
+                    .clearMixins()
+                    .traits(shape.getIntroducedTraits().values());
+            unrollMembers(shape, builder::addMember);
+            return builder.build();
+        }
+
+        @Override
+        public Shape unionShape(UnionShape shape) {
+            UnionShape.Builder builder = shape.toBuilder()
+                    .clearMixins()
+                    .traits(shape.getIntroducedTraits().values());
+            unrollMembers(shape, builder::addMember);
+            return builder.build();
+        }
+
+        private void unrollMembers(Shape shape, Consumer<MemberShape> consumer) {
+            for (MemberShape member : shape.members()) {
+                if (member.getMixins().isEmpty()) {
+                    consumer.accept(member);
+                } else {
+                    consumer.accept((MemberShape) member.accept(this));
+                }
+            }
+        }
+
+        @Override
+        public Shape operationShape(OperationShape shape) {
+            OperationShape.Builder builder = shape.toBuilder()
+                    .clearMixins()
+                    .traits(shape.getIntroducedTraits().values())
+                    .clearErrors();
+
+            Set<ShapeId> previousErrors = new HashSet<>();
+            for (ShapeId mixinId : shape.getMixins()) {
+                previousErrors.addAll(model.expectShape(mixinId, OperationShape.class).getErrors());
+            }
+
+            addIntroduced(shape.getErrors(), previousErrors, builder::addError);
+
+            return builder.build();
+        }
+
+        @Override
+        public Shape serviceShape(ServiceShape shape) {
+            ServiceShape.Builder builder = shape.toBuilder()
+                    .clearMixins()
+                    .clearOperations()
+                    .clearResources()
+                    .clearErrors()
+                    .clearRename()
+                    .traits(shape.getIntroducedTraits().values());
+
+            String previousVersion = "";
+            Set<ShapeId> previousOperations = new HashSet<>();
+            Set<ShapeId> previousResources = new HashSet<>();
+            Set<ShapeId> previousErrors = new HashSet<>();
+            Map<ShapeId, String> previousRename = new HashMap<>();
+
+            for (ShapeId mixinId : shape.getMixins()) {
+                ServiceShape mixin = model.expectShape(mixinId, ServiceShape.class);
+                previousVersion = mixin.getVersion();
+                previousOperations.addAll(mixin.getOperations());
+                previousResources.addAll(mixin.getResources());
+                previousErrors.addAll(mixin.getErrors());
+                previousRename.putAll(mixin.getRename());
+            }
+
+            if (shape.getVersion().equals(previousVersion)) {
+                builder.version("");
+            }
+
+            addIntroduced(shape.getOperations(), previousOperations, builder::addOperation);
+            addIntroduced(shape.getResources(), previousResources, builder::addResource);
+            addIntroduced(shape.getErrors(), previousErrors, builder::addError);
+
+            for (Map.Entry<ShapeId, String> entry : shape.getRename().entrySet()) {
+                if (!entry.getValue().equals(previousRename.get(entry.getKey()))) {
+                    builder.putRename(entry.getKey(), entry.getValue());
+                }
+            }
+
+            return builder.build();
+        }
+
+        private void addIntroduced(
+                Collection<ShapeId> current,
+                Collection<ShapeId> previous,
+                Consumer<ShapeId> consumer
+        ) {
+            for (ShapeId shapeId : current) {
+                if (!previous.contains(shapeId)) {
+                    consumer.accept(shapeId);
+                }
+            }
+        }
+    }
+}
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/EntityShape.java b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/EntityShape.java
index 4d2173e840c..0ad3814fcd9 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/EntityShape.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/EntityShape.java
@@ -27,18 +27,14 @@
 public abstract class EntityShape extends Shape {
 
     private final Set<ShapeId> resources;
-    private final Set<ShapeId> introducedResources;
     private final Set<ShapeId> operations;
-    private final Set<ShapeId> introducedOperations;
 
     EntityShape(Builder<?, ?> builder) {
         super(builder, false);
 
         if (getMixins().isEmpty()) {
             resources = builder.resources.copy();
-            introducedResources = resources;
             operations = builder.operations.copy();
-            introducedOperations = operations;
         } else {
             Set<ShapeId> computedResources = new TreeSet<>();
             Set<ShapeId> computedOperations = new TreeSet<>();
@@ -50,11 +46,8 @@ public abstract class EntityShape extends Shape {
                 computedOperations.addAll(mixin.getOperations());
             }
 
-            introducedResources = builder.resources.copy();
-            introducedOperations = builder.operations.copy();
-
-            computedResources.addAll(introducedResources);
-            computedOperations.addAll(introducedOperations);
+            computedResources.addAll(builder.resources.peek());
+            computedOperations.addAll(builder.operations.peek());
 
             resources = Collections.unmodifiableSet(computedResources);
             operations = Collections.unmodifiableSet(computedOperations);
@@ -68,16 +61,6 @@ public final Set<ShapeId> getResources() {
         return resources;
     }
 
-    /**
-     * Gets all the directly-bound resources introduced by this shape and
-     * not inherited from mixins.
-     *
-     * @return Gets the introduced resources directly-bound to the shape.
-     */
-    public final Set<ShapeId> getIntroducedResources() {
-        return introducedResources;
-    }
-
     /**
      * Gets operations bound only through the "operations" property.
      *
@@ -93,20 +76,6 @@ public final Set<ShapeId> getOperations() {
         return operations;
     }
 
-    /**
-     * Gets operations bound through the "operations" property that
-     * were not inherited from mixins.
-     *
-     * <p>This will not include operations bound to resources using
-     * a lifecycle operation binding. This will also not include
-     * operations bound to this entity through sub-resources.
-     *
-     * @return Gets the introduced operations.
-     */
-    public final Set<ShapeId> getIntroducedOperations() {
-        return introducedOperations;
-    }
-
     /**
      * Get all operations directly bound to this shape.
      *
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ModelSerializer.java b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ModelSerializer.java
index 0c31c645932..b9de110b9c8 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ModelSerializer.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ModelSerializer.java
@@ -29,6 +29,7 @@
 import java.util.stream.Stream;
 import software.amazon.smithy.model.Model;
 import software.amazon.smithy.model.SourceLocation;
+import software.amazon.smithy.model.knowledge.PreMixinIndex;
 import software.amazon.smithy.model.loader.Prelude;
 import software.amazon.smithy.model.node.ArrayNode;
 import software.amazon.smithy.model.node.Node;
@@ -66,7 +67,7 @@ private ModelSerializer(Builder builder) {
     }
 
     public ObjectNode serialize(Model model) {
-        ShapeSerializer shapeSerializer = new ShapeSerializer();
+        ShapeSerializer shapeSerializer = new ShapeSerializer(model);
 
         ObjectNode.Builder builder = Node.objectNodeBuilder()
                 .withMember("smithy", Node.from(Model.MODEL_VERSION))
@@ -204,6 +205,11 @@ private ObjectNode.Builder serializeTraits(ObjectNode.Builder builder, Collectio
     private final class ShapeSerializer extends ShapeVisitor.Default<Node> {
 
         private final Set<MemberShape> mixinMemberTraits = new TreeSet<>();
+        private final PreMixinIndex preMixinIndex;
+
+        private ShapeSerializer(Model model) {
+            preMixinIndex = PreMixinIndex.of(model);
+        }
 
         private ObjectNode.Builder createTypedBuilder(Shape shape) {
             ObjectNode.Builder builder = Node.objectNodeBuilder()
@@ -263,10 +269,11 @@ public Node mapShape(MapShape shape) {
 
         @Override
         public Node operationShape(OperationShape shape) {
+            OperationShape preMixinShape = preMixinIndex.getPreMixinShape(shape).asOperationShape().get();
             return serializeAllTraits(shape, createTypedBuilder(shape)
                     .withMember("input", serializeReference(shape.getInputShape()))
                     .withMember("output", serializeReference(shape.getOutputShape()))
-                    .withOptionalMember("errors", createOptionalIdList(shape.getIntroducedErrors())))
+                    .withOptionalMember("errors", createOptionalIdList(preMixinShape.getErrors())))
                     .build();
         }
 
@@ -288,9 +295,9 @@ public Node resourceShape(ResourceShape shape) {
                     .withOptionalMember("update", shape.getUpdate().map(this::serializeReference))
                     .withOptionalMember("delete", shape.getDelete().map(this::serializeReference))
                     .withOptionalMember("list", shape.getList().map(this::serializeReference))
-                    .withOptionalMember("operations", createOptionalIdList(shape.getIntroducedOperations()))
+                    .withOptionalMember("operations", createOptionalIdList(shape.getOperations()))
                     .withOptionalMember("collectionOperations", createOptionalIdList(shape.getCollectionOperations()))
-                    .withOptionalMember("resources", createOptionalIdList(shape.getIntroducedResources())))
+                    .withOptionalMember("resources", createOptionalIdList(shape.getResources())))
                     .build();
         }
 
@@ -298,17 +305,19 @@ public Node resourceShape(ResourceShape shape) {
         public Node serviceShape(ServiceShape shape) {
             ObjectNode.Builder serviceBuilder = createTypedBuilder(shape);
 
-            if (!StringUtils.isBlank(shape.getIntroducedVersion())) {
-                serviceBuilder.withMember("version", Node.from(shape.getIntroducedVersion()));
+            ServiceShape preMixinShape = preMixinIndex.getPreMixinShape(shape).asServiceShape().get();
+
+            if (!StringUtils.isBlank(preMixinShape.getVersion())) {
+                serviceBuilder.withMember("version", Node.from(preMixinShape.getVersion()));
             }
 
-            serviceBuilder.withOptionalMember("operations", createOptionalIdList(shape.getIntroducedOperations()));
-            serviceBuilder.withOptionalMember("resources", createOptionalIdList(shape.getIntroducedResources()));
-            serviceBuilder.withOptionalMember("errors", createOptionalIdList(shape.getIntroducedErrors()));
+            serviceBuilder.withOptionalMember("operations", createOptionalIdList(preMixinShape.getOperations()));
+            serviceBuilder.withOptionalMember("resources", createOptionalIdList(preMixinShape.getResources()));
+            serviceBuilder.withOptionalMember("errors", createOptionalIdList(preMixinShape.getErrors()));
 
-            if (!shape.getIntroducedRename().isEmpty()) {
+            if (!preMixinShape.getRename().isEmpty()) {
                 ObjectNode.Builder renameBuilder = Node.objectNodeBuilder();
-                for (Map.Entry<ShapeId, String> entry : shape.getIntroducedRename().entrySet()) {
+                for (Map.Entry<ShapeId, String> entry : preMixinShape.getRename().entrySet()) {
                     renameBuilder.withMember(entry.getKey().toString(), entry.getValue());
                 }
                 serviceBuilder.withMember("rename", renameBuilder.build());
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/OperationShape.java b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/OperationShape.java
index d2966c2085b..98518c22d10 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/OperationShape.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/OperationShape.java
@@ -36,7 +36,6 @@ public final class OperationShape extends Shape implements ToSmithyBuilder<Opera
     private final ShapeId input;
     private final ShapeId output;
     private final List<ShapeId> errors;
-    private final List<ShapeId> introducedErrors;
 
     private OperationShape(Builder builder) {
         super(builder, false);
@@ -46,7 +45,6 @@ private OperationShape(Builder builder) {
 
         if (getMixins().isEmpty()) {
             errors = builder.errors.copy();
-            introducedErrors = errors;
         } else {
             // Compute mixin properties of the operation. Input / output are
             // forbidden in operation mixins, so we don't bother with them
@@ -55,8 +53,7 @@ private OperationShape(Builder builder) {
             for (Shape shape : builder.getMixins().values()) {
                 shape.asOperationShape().ifPresent(mixin -> computedErrors.addAll(mixin.getErrors()));
             }
-            introducedErrors = builder.errors.copy();
-            computedErrors.addAll(introducedErrors);
+            computedErrors.addAll(builder.errors.peek());
             errors = Collections.unmodifiableList(new ArrayList<>(computedErrors));
         }
 
@@ -78,7 +75,7 @@ public Builder toBuilder() {
         return updateBuilder(builder())
                 .input(input)
                 .output(output)
-                .errors(getIntroducedErrors());
+                .errors(errors);
     }
 
     @Override
@@ -165,16 +162,6 @@ public List<ShapeId> getErrors() {
         return errors;
     }
 
-    /**
-     * Gets the errors introduced by the shape and not inherited
-     * from mixins.
-     *
-     * @return Returns the introduced errors.
-     */
-    public List<ShapeId> getIntroducedErrors() {
-        return introducedErrors;
-    }
-
     /**
      * <p>Gets a list of the error shape IDs the operation can encounter,
      * including any common errors of a service.
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ServiceShape.java b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ServiceShape.java
index 50234bca8d3..897928af4b0 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ServiceShape.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/ServiceShape.java
@@ -34,22 +34,16 @@
 public final class ServiceShape extends EntityShape implements ToSmithyBuilder<ServiceShape> {
 
     private final String version;
-    private final String introducedVersion;
     private final Map<ShapeId, String> rename;
-    private final Map<ShapeId, String> introducedRename;
     private final List<ShapeId> errors;
-    private final List<ShapeId> introducedErrors;
 
     private ServiceShape(Builder builder) {
         super(builder);
 
         if (getMixins().isEmpty()) {
             version = builder.version;
-            introducedVersion = version;
             rename = builder.rename.copy();
-            introducedRename = rename;
             errors = builder.errors.copy();
-            introducedErrors = errors;
         } else {
             String computedVersion = "";
             Map<ShapeId, String> computedRename = new HashMap<>();
@@ -66,15 +60,11 @@ private ServiceShape(Builder builder) {
                 }
             }
 
-            introducedVersion = builder.version;
-            introducedRename = builder.rename.copy();
-            introducedErrors = builder.errors.copy();
-
-            if (!introducedVersion.isEmpty()) {
-                computedVersion = introducedVersion;
+            if (!builder.version.isEmpty()) {
+                computedVersion = builder.version;
             }
-            computedRename.putAll(introducedRename);
-            computedErrors.addAll(introducedErrors);
+            computedRename.putAll(builder.rename.peek());
+            computedErrors.addAll(builder.errors.peek());
 
             version = computedVersion;
             rename = Collections.unmodifiableMap(computedRename);
@@ -89,11 +79,11 @@ public static Builder builder() {
     @Override
     public Builder toBuilder() {
         return updateBuilder(builder())
-                .version(introducedVersion)
-                .errors(introducedErrors)
-                .rename(introducedRename)
-                .operations(getIntroducedOperations())
-                .resources(getIntroducedResources());
+                .version(version)
+                .errors(errors)
+                .rename(rename)
+                .operations(getOperations())
+                .resources(getResources());
     }
 
     @Override
@@ -128,17 +118,6 @@ public String getVersion() {
         return version;
     }
 
-    /**
-     * Gets the version of the service introduced by the shape and not
-     * inherited from mixins. An empty string is returned if the version
-     * is undefined.
-     *
-     * @return The introduced version of the service.
-     */
-    public String getIntroducedVersion() {
-        return introducedVersion;
-    }
-
     /**
      * @return The rename map of the service.
      */
@@ -146,16 +125,6 @@ public Map<ShapeId, String> getRename() {
         return rename;
     }
 
-    /**
-     * Gets the rename map introduced by the shape and not inherited
-     * from mixins.
-     *
-     * @return The introduced rename map of the service.
-     */
-    public Map<ShapeId, String> getIntroducedRename() {
-        return introducedRename;
-    }
-
     /**
      * <p>Gets a list of the common errors that can be encountered by
      * every operation in the service.</p>
@@ -170,21 +139,6 @@ public List<ShapeId> getErrors() {
         return errors;
     }
 
-    /**
-     * Gets the list of common errors introduced by the shape and not
-     * inherited from mixins. These errors can be encountered by every
-     * operation in the service.
-     *
-     * Each returned {@link ShapeId} must resolve to a
-     * {@link StructureShape} that is targeted by an error trait; however,
-     * this is only guaranteed after a model is validated.
-     *
-     * @return Returns the introduced service errors.
-     */
-    public List<ShapeId> getIntroducedErrors() {
-        return introducedErrors;
-    }
-
     /**
      * Gets the contextual name of a shape within the closure.
      *
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java
index a3a1b586ff3..6a355f01c66 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java
@@ -33,6 +33,7 @@
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import software.amazon.smithy.model.Model;
+import software.amazon.smithy.model.knowledge.PreMixinIndex;
 import software.amazon.smithy.model.loader.Prelude;
 import software.amazon.smithy.model.node.ArrayNode;
 import software.amazon.smithy.model.node.BooleanNode;
@@ -371,6 +372,7 @@ private static final class ShapeSerializer extends ShapeVisitor.Default<Void> {
         private final Predicate<Trait> traitFilter;
         private final Model model;
         private final Set<ShapeId> inlineableShapes;
+        private final PreMixinIndex preMixinIndex;
 
         ShapeSerializer(
                 SmithyCodeWriter codeWriter,
@@ -384,6 +386,7 @@ private static final class ShapeSerializer extends ShapeVisitor.Default<Void> {
             this.traitFilter = traitFilter;
             this.model = model;
             this.inlineableShapes = inlineableShapes;
+            this.preMixinIndex = PreMixinIndex.of(model);
         }
 
         @Override
@@ -550,16 +553,18 @@ public Void serviceShape(ServiceShape shape) {
             writeMixins(shape, false);
             codeWriter.openBlock("{");
 
-            if (!StringUtils.isBlank(shape.getIntroducedVersion())) {
-                codeWriter.write("version: $S", shape.getIntroducedVersion());
+            ServiceShape preMixinShape = preMixinIndex.getPreMixinShape(shape).asServiceShape().get();
+
+            if (!StringUtils.isBlank(preMixinShape.getVersion())) {
+                codeWriter.write("version: $S", preMixinShape.getVersion());
             }
 
-            codeWriter.writeOptionalIdList("operations", shape.getIntroducedOperations());
-            codeWriter.writeOptionalIdList("resources", shape.getIntroducedResources());
-            codeWriter.writeOptionalIdList("errors", shape.getIntroducedErrors());
-            if (!shape.getIntroducedRename().isEmpty()) {
+            codeWriter.writeOptionalIdList("operations", preMixinShape.getOperations());
+            codeWriter.writeOptionalIdList("resources", preMixinShape.getResources());
+            codeWriter.writeOptionalIdList("errors", preMixinShape.getErrors());
+            if (!preMixinShape.getRename().isEmpty()) {
                 codeWriter.openBlock("rename: {", "}", () -> {
-                    for (Map.Entry<ShapeId, String> entry : shape.getIntroducedRename().entrySet()) {
+                    for (Map.Entry<ShapeId, String> entry : preMixinShape.getRename().entrySet()) {
                         codeWriter.write("$S: $S", entry.getKey(), entry.getValue());
                     }
                 });
@@ -589,9 +594,9 @@ public Void resourceShape(ResourceShape shape) {
             shape.getUpdate().ifPresent(shapeId -> codeWriter.write("update: $I", shapeId));
             shape.getDelete().ifPresent(shapeId -> codeWriter.write("delete: $I", shapeId));
             shape.getList().ifPresent(shapeId -> codeWriter.write("list: $I", shapeId));
-            codeWriter.writeOptionalIdList("operations", shape.getIntroducedOperations());
+            codeWriter.writeOptionalIdList("operations", shape.getOperations());
             codeWriter.writeOptionalIdList("collectionOperations", shape.getCollectionOperations());
-            codeWriter.writeOptionalIdList("resources", shape.getIntroducedResources());
+            codeWriter.writeOptionalIdList("resources", shape.getResources());
 
             codeWriter.closeBlock("}");
             codeWriter.write("");
@@ -600,6 +605,7 @@ public Void resourceShape(ResourceShape shape) {
 
         @Override
         public Void operationShape(OperationShape shape) {
+            OperationShape preMixinShape = preMixinIndex.getPreMixinShape(shape).asOperationShape().get();
             serializeTraits(shape);
             codeWriter.writeInline("operation $L ", shape.getId().getName());
             writeMixins(shape, false);
@@ -607,7 +613,7 @@ public Void operationShape(OperationShape shape) {
             List<MemberShape> mixinMembers = new ArrayList<>();
             mixinMembers.addAll(writeInlineableProperty("input", shape.getInputShape(), InputTrait.ID));
             mixinMembers.addAll(writeInlineableProperty("output", shape.getOutputShape(), OutputTrait.ID));
-            codeWriter.writeOptionalIdList("errors", shape.getIntroducedErrors());
+            codeWriter.writeOptionalIdList("errors", preMixinShape.getErrors());
             codeWriter.closeBlock("}");
             codeWriter.write("");
             applyIntroducedTraits(mixinMembers);
diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/PreMixinIndexTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/PreMixinIndexTest.java
new file mode 100644
index 00000000000..6cfad787529
--- /dev/null
+++ b/smithy-model/src/test/java/software/amazon/smithy/model/knowledge/PreMixinIndexTest.java
@@ -0,0 +1,42 @@
+package software.amazon.smithy.model.knowledge;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.jupiter.api.Test;
+import software.amazon.smithy.model.Model;
+import software.amazon.smithy.model.node.Node;
+import software.amazon.smithy.model.node.ObjectNode;
+import software.amazon.smithy.model.shapes.ModelSerializer;
+import software.amazon.smithy.model.shapes.Shape;
+import software.amazon.smithy.model.transform.ModelTransformer;
+
+public class PreMixinIndexTest {
+
+    @Test
+    public void testUnroll() {
+        Model withMixins = Model.assembler()
+                .addImport(OperationIndexTest.class.getResource("premixin.smithy"))
+                .assemble()
+                .unwrap();
+
+        PreMixinIndex index = PreMixinIndex.of(withMixins);
+        Set<Shape> updatedShapes = new HashSet<>();
+        withMixins.shapes().forEach(shape -> updatedShapes.add(index.getPreMixinShape(shape)));
+
+        Model actual = ModelTransformer.create().replaceShapes(withMixins, updatedShapes);
+
+        Model expected = Model.assembler()
+                .addImport(OperationIndexTest.class.getResource("premixin-unrolled.smithy"))
+                .assemble()
+                .unwrap();
+
+        if (!actual.equals(expected)) {
+            ModelSerializer serializer = ModelSerializer.builder().build();
+            ObjectNode actualNode = serializer.serialize(actual);
+            ObjectNode expectedNode = serializer.serialize(expected);
+
+            Node.assertEquals(actualNode, expectedNode);
+        }
+    }
+
+}
diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/premixin-unrolled.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/premixin-unrolled.smithy
new file mode 100644
index 00000000000..2d241aac016
--- /dev/null
+++ b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/premixin-unrolled.smithy
@@ -0,0 +1,89 @@
+$version: "2.0"
+
+namespace smithy.example
+
+@private
+service MixedService {
+    version: "2022-01-01"
+    operations: [
+        MixedServiceOperation
+    ]
+    resources: [
+        MixedResource
+    ]
+    errors: [
+        MixedError
+    ]
+    rename: {
+        "smithy.example#MixedRename": "LocalRename"
+    }
+}
+
+@internal
+@mixin
+service MixinService {
+    version: "2021-12-31"
+    operations: [
+        MixinServiceOperation
+    ]
+    resources: [
+        MixinResource
+    ]
+    errors: [
+        MixinError
+    ]
+    rename: {
+        "smithy.example#MixinRename": "UpstreamRename"
+    }
+}
+
+resource MixedResource {
+}
+
+resource MixinResource {
+}
+
+@mixin
+@internal
+operation MixinOperation {
+    errors: [MixinError]
+}
+
+@private
+operation MixedOperation {
+    errors: [MixedError]
+}
+
+operation MixedServiceOperation {
+    input: Unit
+    output: Unit
+}
+
+operation MixinServiceOperation {
+    input: Unit
+    output: Unit
+}
+
+@error("server")
+structure MixedError {
+    message: MixedRename
+}
+
+@error("client")
+structure MixinError {
+    message: MixinRename
+    state: OverriddenRename
+}
+
+string MixedRename
+
+string MixinRename
+
+@mixin
+@internal
+string MixinString
+
+@private
+string MixedString
+
+string OverriddenRename
diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/premixin.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/premixin.smithy
new file mode 100644
index 00000000000..cc59b3a18eb
--- /dev/null
+++ b/smithy-model/src/test/resources/software/amazon/smithy/model/knowledge/premixin.smithy
@@ -0,0 +1,89 @@
+$version: "2.0"
+
+namespace smithy.example
+
+@private
+service MixedService with MixinService {
+    version: "2022-01-01"
+    operations: [
+        MixedServiceOperation
+    ]
+    resources: [
+        MixedResource
+    ]
+    errors: [
+        MixedError
+    ]
+    rename: {
+        "smithy.example#MixedRename": "LocalRename"
+    }
+}
+
+@internal
+@mixin
+service MixinService {
+    version: "2021-12-31"
+    operations: [
+        MixinServiceOperation
+    ]
+    resources: [
+        MixinResource
+    ]
+    errors: [
+        MixinError
+    ]
+    rename: {
+        "smithy.example#MixinRename": "UpstreamRename"
+    }
+}
+
+resource MixedResource {
+}
+
+resource MixinResource {
+}
+
+@mixin
+@internal
+operation MixinOperation {
+    errors: [MixinError]
+}
+
+@private
+operation MixedOperation with MixinOperation {
+    errors: [MixedError]
+}
+
+operation MixedServiceOperation {
+    input: Unit
+    output: Unit
+}
+
+operation MixinServiceOperation {
+    input: Unit
+    output: Unit
+}
+
+@error("server")
+structure MixedError {
+    message: MixedRename
+}
+
+@error("client")
+structure MixinError {
+    message: MixinRename
+    state: OverriddenRename
+}
+
+string MixedRename
+
+string MixinRename
+
+@mixin
+@internal
+string MixinString
+
+@private
+string MixedString with MixinString
+
+string OverriddenRename