Upstream components are other parts of the system that your component depends on to do its job.
If the design of an upstream component changes, the ability of your component to function may be affected.
If an upstream component has a bug, this bug may be manifested in your component.
Downstream components are parts of the system that your component can affect.
Changes in your component can ripple to components that are downstream from your component.
Consider an application that consists of a database tier and an application tier.
The database tier would be considered to be upstream of the application tier.
The reason behind why I use the flow 'direction' I do (e.g. downstream services are those my service can affect, and upstream services are those services I rely upon and who can affect me) is related to the flow of water.
If you look at a mountain stream, the water flows from the top of the mountain ...'downstream'. If a large rock falls upon the path halfway up the mountain, then that will of course prevent the water from flowing further (the water flow has been restricted). Any people at the bottom (i.e. downstream) of the mountain will be affected by this rock falling on the stream from above (i.e. upstream) their own position.
This was really helpful, thanks 🙂