The migration creates the data model (and potentially updates data) on the database server.
The schema (specifically Ecto schema) is a representation of that model within Elixir so that your Elixir code can interact with it. Some systems (e.g. Entity Framework in .Net) can automatically generate migrations from changes detected in the schema, but Ecto can’t. If you don’t use the generators (e.g. mix phx.html.gen) then you have to code both the schema and the migration.
(Just to complicate things, you can also have an Ecto schema with no corresponding tables in the database…)
Want to add that it is possible to have also multiple schemas for the same table dependind on the context you’re using it. For example some fields or changesets are useful for a specific context and not for another one. Maybe you want also to assign different default value to some fields depending on the context…