agentleFS
OleanderHQOleanderHQ/skills/skills/spark-best-practices/SKILL.md

spark-best-practices

Skill1 starsChanged 3 months agoApache-2.0View on GitHub

General Apache Spark best practices for scalable, maintainable DataFrame jobs: avoid driver materialization, reduce shuffle, join efficiently, and cache carefully. Use when optimizing Spark performance, reviewing PySpark jobs, or writing new DataFrame pipelines.

2 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions2 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 2

    1. baekenough/oh-my-customcode★ 42same name
    2. BigDataBoutique/skills★ 2same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository6 other files it gives its agents.

The file

Show its rules and text

We split this skill into the rules it gives an agent

13 rules. About 0 are common, 8 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill for general Apache Spark guidance when optimizing performance, reliability, and maintainability.

    line 12
  2. Very specific:

    Avoid collect(), toPandas(), and large take() in core data paths.

    line 16
  3. Distinctive:

    Keep heavy transformation and write paths in Spark DataFrame execution.

    line 18
  4. Distinctive:

    Use Spark SQL/DataFrame functions so Catalyst can optimize execution plans.

    line 22
  5. Distinctive:

    Avoid row-by-row Python logic when equivalent DataFrame expressions exist.

    line 23
  6. Distinctive:

    Keep transformations declarative and composable.

    line 24
  7. Very specific:

    Use coalesce when reducing output partitions.

    line 30
  8. Distinctive:

    Consider checkpointing for very long lineage plans.

    line 43
  9. Very specific:

    Prefer columnar formats (Parquet/Delta/Iceberg) when possible.

    line 47
  10. Distinctive:

    Avoid small file explosion.

    line 49
  11. Very specific:

    Use explain() and execution metrics/logs to inspect physical plans and shuffle boundaries.

    line 59
  12. Distinctive:

    Every Structured Streaming query needs a stable checkpoint location.

    line 65
  13. Very specific:

    Use shared storage for cluster runs, not local /tmp, because executors must be able to see the same checkpoint path.

    line 69

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Spark Best Practices

Use this skill for general Apache Spark guidance when optimizing performance, reliability, and maintainability.

1) Keep execution distributed

  • Avoid collect(), toPandas(), and large take() in core data paths.
  • Materialize to driver memory only for very small control outputs (metrics, IDs, summaries).
  • Keep heavy transformation and write paths in Spark DataFrame execution.

2) Prefer DataFrame APIs to Python loops

  • Use Spark SQL/DataFrame functions so Catalyst can optimize execution plans.
  • Avoid row-by-row Python logic when equivalent DataFrame expressions exist.
  • Keep transformations declarative and composable.

3) Reduce shuffle cost

  • Project and filter early to reduce data volume before joins/aggregations.
  • Repartition intentionally before heavy joins/writes.
  • Use coalesce when reducing output partitions.
  • Watch for skewed keys and apply skew mitigation.

4) Use efficient joins

  • Broadcast small dimension tables when appropriate.
  • Align join key types and null handling before joins.
  • Validate expected join cardinality to avoid explosive outputs.

5) Cache only reused intermediates

  • Cache/persist DataFrames only when reused across multiple downstream actions.
  • Unpersist promptly when no longer needed.
  • Consider checkpointing for very long lineage plans.

6) Write in table-friendly layouts

  • Prefer columnar formats (Parquet/Delta/Iceberg) when possible.
  • Partition by bounded-cardinality business keys.
  • Avoid small file explosion; compact files when needed.

7) Be explicit with schema and quality

  • Define schemas explicitly where practical.
  • Normalize data types across sources before joins/unions.
  • Handle null semantics intentionally in filters, joins, and aggregations.

8) Observe and verify

  • Use explain() and execution metrics/logs to inspect physical plans and shuffle boundaries.
  • Track row counts and key metrics at major steps.
  • Compare runtime and output quality after each optimization pass.

9) Set Structured Streaming checkpoints

Every Structured Streaming query needs a stable checkpoint location. The checkpoint stores progress metadata and, for stateful queries such as windows, state-store data that Spark needs to recover correctly.

Use shared storage for cluster runs, not local /tmp, because executors must be able to see the same checkpoint path.

oleander provides spark.oleander.app.state.dir as a shared application state directory that users can use for streaming checkpoints.

from pyspark.sql import SparkSession
from pyspark.sql.functions import col, count, window

spark = SparkSession.builder.appName("message-counts").getOrCreate()

state_dir = spark.conf.get("spark.oleander.app.state.dir", "").strip()
checkpoint = f"{state_dir.rstrip('/')}/public-stream/checkpoints/message-counts"

events = (
    spark.readStream.format("kafka")
    .option("kafka.bootstrap.servers", "localhost:9092")
    .option("subscribe", "messages")
    .load()
)

counts = (
    events.selectExpr("CAST(value AS STRING) AS body", "timestamp AS event_time")
    .withWatermark("event_time", "1 minute")
    .groupBy(window(col("event_time"), "1 minute"))
    .agg(count("*").alias("message_count"))
)

query = (
    counts.writeStream
    .format("console")
    .outputMode("append")
    .option("checkpointLocation", checkpoint)
    .start()
)

query.awaitTermination()

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.