Software design helps me understand and resolve problems before they are manifested in code. While designing I use plenty of diagrams, some of which are shown below. Some pointers are given to tools you can use and when they are appropriate.
Show the components in play, gray out the less important ones. Keep names as specific as possible, ie. use postgres over database, unless that component can be dynamically replaced.
Use image maps to link components to more detailed instructions, e.g. for graphviz
dot -Tcmapx graph.gvWork more freely with automatic preview using xdot
xdot -f dot graph.gvGraphviz source: all.gv
Serviced - component details
Details could include interfaces and or packages depending on size.Graphviz source: serviced.gv
Service - class diagram
Show relations between structs (classes) and the important methods. Good when designing data and expected behaviour. Don't cram in every detail, just what is needed to convey a certain feature.
Graphviz source: service.gv
Middleware - sequence diagram
Use sequence diagrams to illustrate important paths in your callstack.
Mscgen source: middleware.msc
Pipelines and states transitions in your applications are best visualized with state diagrams.
Graphviz source: state.gv
Choose one and stick with it. Remember black and white goes a long way.
Graphviz source: colors.gv