             return cache
         }
 
-        let customPayload: CustomMessagePayload = {
-            if var given = self.customPayload {
-                given.aps = payload
-                return given
-            } else {
-                return DummyCustomPayload(aps: payload)
-            }
-        }()
-
-        let raw = try customPayload.jsonRepresentation()
+        struct FinalPayload: Encodable {
+
+            enum CodingKeys: CodingKey {
+
+                case aps
+            }
+
+            let aps: Payload
+            let custom: Encodable?
+
+            func encode(to encoder: Encoder) throws {
+                // encode custom payload first
+                try custom?.encode(to: encoder)
+
+                // so that `aps` key get's overwritten in case it's been used
+                var container = encoder.container(keyedBy: CodingKeys.self)
+                try container.encode(aps, forKey: .aps)
+            }
+        }
+
+        let final = FinalPayload(aps: payload, custom: customPayload)
+        let raw = try JSONEncoder().encode(final)
         encodedDataCache = raw
         return raw
     }

//
import libc
import Foundation

public protocol CustomMessagePayload: Encodable {

    /// Must be encoded using `aps` key
    var aps: Message.Payload? { get set }
}

private extension Encodable {

    func jsonRepresentation() throws -> Data {
        return try JSONEncoder().encode(self)
    }
}

extension CustomMessagePayload {

    public var payloadKey: StaticString {
        return "aps"
    }
}

fileprivate struct DummyCustomPayload: CustomMessagePayload {

    var aps: Message.Payload?
}

/**
 APNS's message

        }
    }

    public var customPayload: Encodable? {
        willSet {
            encodedDataCache = nil
        }
