What do NOT NULL and DEFAULT actually do, and when do you need one without the other?
NOT NULL is a rule: the column must hold a value on every row. DEFAULT is a fill-in: if the INSERT does not supply a value for the column, the engine substitutes the expression you declared. They are independent, and the combinations are all meaningful.
NOT NULL without DEFAULT means the caller must supply the value on every insert, and the insert fails with a constraint error if they do not. That is right for a column whose value genuinely cannot be invented — a person's name, an order's total, an account's currency.
DEFAULT without NOT NULL means the column has a sensible fallback but a caller may still override it, and may still explicitly store NULL. That is right for a column where a default is helpful but NULL is a legitimate value — the tier of a customer, which defaults to 'standard' but might be recorded as unknown.
Both together are the most common combination, and they are subtly different things. The column always holds a value, and if the caller does not supply one, the default is used. This is what you want for a status column that starts at 'new' and must never be blank.
The important detail is that a DEFAULT only fires when the column is omitted from the INSERT or given the DEFAULT keyword. Supplying an explicit NULL is a different thing entirely, and how it behaves depends on the column's NOT NULL declaration — which is the question that trips people up.