diff --git a/avro.cabal b/avro.cabal
--- a/avro.cabal
+++ b/avro.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 686c91bf89cf070fdd57de52066edac6394a61472b3927e5c8fab77a5c009ba1
+-- hash: fcff216c51da7f4f507714e81688ee3d9c149e101ffbe1b7051f4559eb2feebb
 
 name:           avro
-version:        0.3.6.1
+version:        0.4.0.0
 synopsis:       Avro serialization support for Haskell
 description:    Avro serialization and deserialization support for Haskell
 category:       Data
@@ -21,18 +21,17 @@
     ChangeLog.md
     test/data/deconflict/reader.avsc
     test/data/deconflict/writer.avsc
-    test/data/enums-object.json
     test/data/enums.avsc
     test/data/internal-bindings.avsc
     test/data/karma.avsc
     test/data/logical.avsc
     test/data/maybe.avsc
-    test/data/namespace-inference.json
+    test/data/overlay/composite.avsc
+    test/data/overlay/expectation.avsc
+    test/data/overlay/primitives.avsc
     test/data/record.avsc
     test/data/reused.avsc
     test/data/small.avsc
-    test/data/unions-object-a.json
-    test/data/unions-object-b.json
     test/data/unions.avsc
 
 source-repository head
diff --git a/test/data/enums-object.json b/test/data/enums-object.json
deleted file mode 100644
--- a/test/data/enums-object.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"id":37,"name":"blarg","reason":"Instead"}
diff --git a/test/data/namespace-inference.json b/test/data/namespace-inference.json
deleted file mode 100644
--- a/test/data/namespace-inference.json
+++ /dev/null
@@ -1,154 +0,0 @@
-[
-  {
-    "type" : "record",
-    "name" : "com.example.Foo",
-    "aliases" : ["FooBar", "com.example.not.Bar"],
-    "doc" : "An example schema to test namespace handling.",
-    "order" : "ascending",
-    "fields" : [
-      {
-        "name" : "bar",
-        "aliases" : [],
-        "order" : "ascending",
-        "type" : {
-          "type" : "record",
-          "name" : "Bar",
-          "order" : "ascending",
-          "aliases" : ["Bar2", "com.example.not.Foo"],
-          "fields" : [
-            {
-              "name" : "baz",
-              "aliases" : [],
-              "order" : "ascending",
-              "type" : {
-                "type" : "record",
-                "order" : "ascending",
-                "name" : "com.example.baz.Baz",
-                "aliases" : ["com.example.Bazzy"],
-                "fields" : [
-                  {
-                    "name"    : "baz",
-                    "type"    : "Baz",
-                    "aliases" : [],
-                    "order"   : "ascending"
-                  },
-                  {
-                    "name"    : "bazzy",
-                    "type"    : "com.example.Bazzy",
-                    "aliases" : [],
-                    "order"   : "ascending"
-                  }
-                ]
-              }
-            },
-            {
-              "name"    : "bazzy",
-              "type"    : "Bazzy",
-              "aliases" : [],
-              "order"   : "ascending"
-            }
-          ]
-        }
-      },
-      {
-        "name"    : "baz",
-        "type"    : "com.example.baz.Baz",
-        "aliases" : [],
-        "order"   : "ascending"
-      }
-    ]
-  },
-  {
-    "type" : "record",
-    "name" : "Foo",
-    "namespace" : "com.example",
-    "aliases" : ["FooBar", "com.example.not.Bar"],
-    "doc" : "An example schema to test namespace handling.",
-    "fields" : [
-      {
-        "name" : "bar",
-        "namespace" : "com.example",
-        "type" : {
-          "type" : "record",
-          "name" : "Bar",
-          "aliases" : ["Bar2", "com.example.not.Foo"],
-          "fields" : [
-            {
-              "name" : "baz",
-              "type" : {
-                "type" : "record",
-                "name" : "Baz",
-                "namespace" : "com.example.baz",
-                "aliases" : ["com.example.Bazzy"],
-                "fields" : [
-                  {
-                    "name" : "baz",
-                    "type" : "Baz"
-                  },
-                  {
-                    "name" : "bazzy",
-                    "type" : "com.example.Bazzy"
-                  }
-                ]
-              }
-            },
-            {
-              "name" : "bazzy",
-              "type" : "Bazzy"
-            }
-          ]
-        }
-      },
-      {
-        "name" : "baz",
-        "type" : "com.example.baz.Baz"
-      }
-    ]
-  },
-  {
-    "type" : "record",
-    "name" : "com.example.Foo",
-    "namespace" : "should.be.ignored",
-    "aliases" : ["FooBar", "com.example.not.Bar"],
-    "doc" : "An example schema to test namespace handling.",
-    "fields" : [
-      {
-        "name" : "bar",
-        "type" : {
-          "type" : "record",
-          "name" : "Bar",
-          "aliases" : ["Bar2", "com.example.not.Foo"],
-          "fields" : [
-            {
-              "name" : "baz",
-              "type" : {
-                "type" : "record",
-                "name" : "com.example.baz.Baz",
-                "namespace" : "should.be.ignored",
-                "aliases" : ["com.example.Bazzy"],
-                "fields" : [
-                  {
-                    "name" : "baz",
-                    "type" : "Baz"
-                  },
-                  {
-                    "name" : "bazzy",
-                    "type" : "com.example.Bazzy"
-                  }
-                ]
-              }
-            },
-            {
-              "name" : "bazzy",
-              "type" : "Bazzy"
-            }
-          ]
-        }
-      },
-      {
-        "name" : "baz",
-        "type" : "com.example.baz.Baz"
-      }
-    ]
-  }
-]
diff --git a/test/data/overlay/composite.avsc b/test/data/overlay/composite.avsc
new file mode 100644
--- /dev/null
+++ b/test/data/overlay/composite.avsc
@@ -0,0 +1,39 @@
+{
+  "type": "record",
+  "name": "composite",
+  "fields": [
+    {
+      "name": "foo-bar-field",
+      "type": "avro.test.data.overlay.primitive.foo-bar"
+    },
+    {
+      "name": "foo-enum-field",
+      "type": "avro.test.data.overlay.primitive.foo-enumeration"
+    },
+    {
+      "name": "foo-fixed-field",
+      "type": "avro.test.data.overlay.primitive.foo-fixed"
+    },
+    {
+      "name": "foo-union-1",
+      "type": "avro.test.data.overlay.primitive.foo-union-1"
+    },
+    {
+      "name": "foo-bar-array",
+      "type": "array",
+      "items": "avro.test.data.overlay.primitive.foo-bar"
+    },
+    {
+      "name": "foo-bar-map",
+      "type": "map",
+      "values": "avro.test.data.overlay.primitive.foo-bar"
+    },
+    {
+      "name": "foo-bar-int-union",
+      "type": [
+        "int",
+        "avro.test.data.overlay.primitive.foo-bar"
+      ]
+    }
+  ]
+}
diff --git a/test/data/overlay/expectation.avsc b/test/data/overlay/expectation.avsc
new file mode 100644
--- /dev/null
+++ b/test/data/overlay/expectation.avsc
@@ -0,0 +1,91 @@
+{
+  "type": "record",
+  "name": "composite",
+  "fields": [
+    {
+      "name": "foo-bar-field",
+      "type": {
+        "type": "record",
+        "name": "avro.test.data.overlay.primitive.foo-bar",
+        "fields": [
+          {
+            "name": "field2.1",
+            "type": "int"
+          }
+        ]
+      }
+    },
+    {
+      "name": "foo-enum-field",
+      "type": {
+        "type": "enum",
+        "name": "avro.test.data.overlay.primitive.foo-enumeration",
+        "symbols": ["fe1", "fe2"]
+      }
+    },
+    {
+      "name": "foo-fixed-field",
+      "type": {
+        "type": "fixed",
+        "name": "avro.test.data.overlay.primitive.foo-fixed",
+        "size": 2
+      }
+    },
+    {
+      "name": "foo-union-1",
+      "type": {
+        "type": "record",
+        "name": "avro.test.data.overlay.primitive.foo-union-1",
+        "fields": [ { "name" : "foo-union-1.1", "type": "int"} ]
+      }
+    },
+    {
+      "name": "foo-bar-array",
+      "type": {
+        "type": "array",
+        "items": {
+          "type": "record",
+          "name": "avro.test.data.overlay.primitive.foo-bar",
+          "fields": [
+            {
+              "name": "field2.1",
+              "type": "int"
+            }
+          ]
+        }
+      }
+    },
+    {
+      "name": "foo-bar-map",
+      "type": {
+        "type": "map",
+        "values": {
+          "type": "record",
+          "name": "avro.test.data.overlay.primitive.foo-bar",
+          "fields": [
+            {
+              "name": "field2.1",
+              "type": "int"
+            }
+          ]
+        }
+      }
+    },
+    {
+      "name": "foo-bar-int-union",
+      "type": [
+        "int",
+        {
+          "type": "record",
+          "name": "avro.test.data.overlay.primitive.foo-bar",
+          "fields": [
+            {
+              "name": "field2.1",
+              "type": "int"
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/test/data/overlay/primitives.avsc b/test/data/overlay/primitives.avsc
new file mode 100644
--- /dev/null
+++ b/test/data/overlay/primitives.avsc
@@ -0,0 +1,51 @@
+{
+  "type": "record",
+  "name": "foo",
+  "namespace": "avro.test.data.overlay.primitive",
+  "fields": [
+    {
+      "name": "field1",
+      "type": "int"
+    },
+    {
+      "name": "field2",
+      "type": {
+        "type": "record",
+        "name": "foo-bar",
+        "fields": [
+          {
+            "name": "field2.1",
+            "type": "int"
+          }
+        ]
+      }
+    },
+    {
+      "name": "field3",
+      "type": {
+        "type": "enum",
+        "name": "foo-enumeration",
+        "symbols": ["fe1", "fe2"]
+      }
+    },
+    {
+      "name": "field4",
+      "type": {
+        "type": "fixed",
+        "name": "foo-fixed",
+        "size": 2
+      }
+    },
+    {
+      "name": "field5",
+      "type": [
+        "string",
+        {
+          "type": "record",
+          "name": "foo-union-1",
+          "fields": [ { "name" : "foo-union-1.1", "type": "int"} ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/test/data/unions-object-a.json b/test/data/unions-object-a.json
deleted file mode 100644
--- a/test/data/unions-object-a.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "scalars": {
-    "string": "blarg"
-  },
-  "nullable": null,
-  "records": {
-    "haskell.avro.example.Foo": {
-      "stuff": "stuff"
-    }
-  },
-  "sameFields": {
-    "haskell.avro.example.Foo": {
-      "stuff": "foo stuff"
-    }
-  },
-  "three": { "int": 37 },
-  "four": { "string": "foo" },
-  "five": {
-    "haskell.avro.example.Foo": { "stuff": "foo stuff" }
-  }
-}
diff --git a/test/data/unions-object-b.json b/test/data/unions-object-b.json
deleted file mode 100644
--- a/test/data/unions-object-b.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "scalars": {
-    "long": 37
-  },
-  "nullable": {
-    "int": 42
-  },
-  "records": {
-    "haskell.avro.example.Bar": {
-      "stuff": "stuff",
-      "things": {
-        "stuff": "things"
-      }
-    }
-  },
-  "sameFields": {
-    "haskell.avro.example.NotFoo": {
-      "stuff": "not foo stuff"
-    }
-  },
-  "three": { "long": 37 },
-  "four": {
-    "haskell.avro.example.Foo": { "stuff" : "foo stuff" }
-  },
-  "five": {
-    "haskell.avro.example.NotFoo": { "stuff": "not foo stuff" }
-  }
-}
