You can think of embedded schemas just as convenience to declare the data+types together. But you don’t need them. For example, you can also do this:
defmodule Post do
defstruct :title
end
data = %Post{}
types = %{title: :string}
Ecto.Changeset.cast({data, types}, params, [:title])
and it would work the same.